These are chat archives for dropbox/pyston

13th
Apr 2015
Marius Wachtler
@undingen
Apr 13 2015 08:58
I benchmarked raising 1000 times an exception and catching it in -I mode. getTraceback needs about 110ms. I then tried to write a custom backtrace function for the interpreter using __builtin_frame_address this one takes 20ms. Sadly we can't use it because it will not work for JITed stuff because we are unable to retrieve the current statement :-(
Marius Wachtler
@undingen
Apr 13 2015 09:20
actually it looks like this will work also for JITed stuff because the current_stmt will be a constant and not in a register. I don't know if the performance improvement is worth the hack. I will create a pull request so you can see what I changed and let you guys decide.
Michael Arntzenius
@rntz
Apr 13 2015 17:02
@undingen So the perf improvement here is coming from avoiding libunwind, I guess?
Marius Wachtler
@undingen
Apr 13 2015 17:02
yes
but it only works for getting the traceback
because for other stuff I think we have to access the values in registers / stack for JITed functions
I mean stuff like getting the local variables etc...
Michael Arntzenius
@rntz
Apr 13 2015 17:05
Hm, makes sense.
I guess libunwind has to keep track of that information whether we need it or not.
Chris Toshok
@toshok
Apr 13 2015 17:06
we might be able to just supply our own _Unwind_Find_FDE. if i remember right the two linked list it uses aren’t static
Marius Wachtler
@undingen
Apr 13 2015 17:06
exactly I think walking the stack using the exception table info adds some overhead.
Chris Toshok
@toshok
Apr 13 2015 17:06
oh it adds tons :)
Michael Arntzenius
@rntz
Apr 13 2015 17:07
so, the thing is
the way we're doing unwinding for exceptions is wrong anyway
Chris Toshok
@toshok
Apr 13 2015 17:07
i still think using a binary search will likely make all the problems go away
spent some time rebuilding libgcc with the llvm patch in a local vm and gave up after hours. will probably do it on jitdev today
Michael Arntzenius
@rntz
Apr 13 2015 17:07
we grab the whole traceback, and then unwind the stack running exception handlers, finally blocks etc.
but CPython does the traceback iteratively, between the point where the exception is thrown & caught
Chris Toshok
@toshok
Apr 13 2015 17:08
oh hm.. do we need to do that? if you catch an exception can you see stack frames above you?
Michael Arntzenius
@rntz
Apr 13 2015 17:08
I believe in Pyston you can and in CPython you can't
Chris Toshok
@toshok
Apr 13 2015 17:08
ahh, interesting
Marius Wachtler
@undingen
Apr 13 2015 17:09
@toshok but even if I disable the JIT, the tracebacks take quite some time to generate. Or would the binary search help in this case too?
Chris Toshok
@toshok
Apr 13 2015 17:09
it depends on if libunwind uses the libgcc stuff. if it does then it would help
Michael Arntzenius
@rntz
Apr 13 2015 17:10
hm, but I thought the reason libgcc was slow was because JITting caused lots of FDEs?
Chris Toshok
@toshok
Apr 13 2015 17:10
it wouldn’t help as much in the jit case, though
there will be a lot of FDE’s regardless, it’s that the jit actually generates 1 ELF object per function with 1 FDE in it
Michael Arntzenius
@rntz
Apr 13 2015 17:11
right right, it's lots of objects not lots of FDEs that is the problem
ok
Marius Wachtler
@undingen
Apr 13 2015 17:11
ok, I read that it is recommended to use libatomic_ops when building libunwind because it should improve the performance. But I did not see a perf difference for my small test.
Chris Toshok
@toshok
Apr 13 2015 17:11
in fact locating an FDE inside an object already uses a binary search iirc
Michael Arntzenius
@rntz
Apr 13 2015 17:23
@toshok Do you know offhand which function(s) in our codebase are the ones which actually cause the call to _Unwind_Find_FDE?
Chris Toshok
@toshok
Apr 13 2015 17:24
the raiseExc* ones do, indirectly. the c++ exception handling stuff (in libstdc++?) calls into it
Michael Arntzenius
@rntz
Apr 13 2015 17:25
right, of course.
Chris Toshok
@toshok
Apr 13 2015 17:25
it might all be in libgcc, actually
Michael Arntzenius
@rntz
Apr 13 2015 20:17
hm, do we garbage-collect JITted code? and if we do, do we tell libgcc & libunwind to unregister the associated stack-tracing information?
Chris Toshok
@toshok
Apr 13 2015 20:19
we don’t
Kevin Modzelewski
@kmod
Apr 13 2015 20:25
@undingen I'm a little wary of changing getTraceback for the reasons that rntz mentioned -- eventually that method will disappear
but I think libunwind always checks for dwarf unwind info first, and then only falls back on rbp-based unwinding if it didn't find dwarf info
maybe we could change it to always do rbp-based unwinding?
Kevin Modzelewski
@kmod
Apr 13 2015 20:30
@toshok maybe instead of modifying libgcc we could use the __register_frame and __deregister_frame api?
Chris Toshok
@toshok
Apr 13 2015 20:32
__register_frame actually allocates an object and puts it into the unseen list
Kevin Modzelewski
@kmod
Apr 13 2015 20:35
but could we __deregister_frame all of our single-fde eh_frame sections, combine them together, and then __register_frame that?
Chris Toshok
@toshok
Apr 13 2015 20:36
I believe so. if we could reliably collect them
Kevin Modzelewski
@kmod
Apr 13 2015 20:36
it doesn't solve the whole problem but could be a quicker band-aid until we have michael's unwinder
which presumably won't use libgcc at all
yeah, freeing code will definitely become harder :P but I think that we won't be doing that until after we have a custom unwinder
Michael Arntzenius
@rntz
Apr 13 2015 20:39
hm, so libgcc knows about our JITted functions because LLVM calls into it when it jits them, is that right?
Chris Toshok
@toshok
Apr 13 2015 20:39
yes
Michael Arntzenius
@rntz
Apr 13 2015 20:39
and libunwind knows about them because we call _U_dyn_register?
(in unwinding.cpp, in TracebacksEventListener::NotifyObjectEmitted, it looks like)
Chris Toshok
@toshok
Apr 13 2015 20:40
we might be able to force llvm to use whatever our unwind system is:
  InstallExceptionTableRegister(__register_frame);
  InstallExceptionTableDeregister(__deregister_frame);
oh, that’s from llvm 3.3. but presumably there’s something similar in trunk
Michael Arntzenius
@rntz
Apr 13 2015 20:41
oh, neat
hm, are there docs for __register_frame anywhere?
Kevin Modzelewski
@kmod
Apr 13 2015 20:49
not sure about docs, but I was taking a look at http://llvm.org/docs/doxygen/html/RTDyldMemoryManager_8cpp_source.html
Michael Arntzenius
@rntz
Apr 13 2015 20:51
ah, the comments in that file seem useful
Chris Toshok
@toshok
Apr 13 2015 20:51
yeah I’m not sure there is. i doubt it, actually. there’s the gcc source on github at least: https://github.com/gcc-mirror/gcc/blob/gcc-4_9-branch/libgcc/unwind-dw2-fde.c#L110
will the new unwinder also handle unwinding through c++ frames?
Michael Arntzenius
@rntz
Apr 13 2015 20:53
well, it'll have to
we need to run destructors, after all.
Chris Toshok
@toshok
Apr 13 2015 20:53
nod. unless we do terrible hacks
and can somehow always identify a callsite as python or c++ (at compile time)
Michael Arntzenius
@rntz
Apr 13 2015 20:55
it's not clear to me how that would help?
what C++ code are you thinking about, Pyston's source, or some external thing we're calling into/out of?
Chris Toshok
@toshok
Apr 13 2015 20:56
both
for long runs of python code we’d use our own unwinder, at a boundary between c++/python we’d have to translate into the other type of exception and essentially rethrow
i’m not suggesting it as a way forward :)
Michael Arntzenius
@rntz
Apr 13 2015 20:59
ah, I see. Yeah, unless there's really no way to get C++-compatible exceptions/unwinding to go fast, we probably don't want to do taht.
*that.
Marius Wachtler
@undingen
Apr 13 2015 21:01
You could also take a look at llvm's implementation: https://github.com/llvm-mirror/libcxxabi/blob/78a89883892ffa56501790c786b228519272cad9/src/Unwind/libunwind.cpp (_unw_add_dynamic_fde is called by __register_frame)
Michael Arntzenius
@rntz
Apr 13 2015 21:02
hm, why on earth does LLVM have their own unwinder
Marius Wachtler
@undingen
Apr 13 2015 21:02
licence I think
Chris Toshok
@toshok
Apr 13 2015 21:06
Ohh I looked to see if LLVM had their own and couldn't find it
Marius Wachtler
@undingen
Apr 13 2015 22:45
http://lists.cs.uiuc.edu/pipermail/llvmdev/2015-April/084459.html The LLILC project (we pronounce it "lilac") is a new effort started at Microsoft to produce MSIL code generators based on LLVM and targeting the open source dotnet CoreCLR (https://github.com/dotnet/coreclr)
Chris Toshok
@toshok
Apr 13 2015 22:46
interesting
is the lineno field in our AST structs encoded in some fashion?
100059 seems a little off
Marius Wachtler
@undingen
Apr 13 2015 22:47
In debug builds it will get set i nthe constructor to 10000 or so
and increment for every node
Chris Toshok
@toshok
Apr 13 2015 22:47
ahh
Marius Wachtler
@undingen
Apr 13 2015 22:48
in order to find where it is not set
Having more people interested in using llvm for JIT sound good :-)
Chris Toshok
@toshok
Apr 13 2015 22:50
oh they’re talking about using the llvm jit interface? I’d assumed they were having llvm spit out IL so you could compiler more languages to run on .net reads article
huh, nice
Marius Wachtler
@undingen
Apr 13 2015 22:57