freenode/#clasp - IRC Chatlog
Search
12:35:22
drmeister
I can only do about 2,000 unwinds/second on this machine with nothing else going on.
12:36:25
drmeister
scymtym: Hi - yeah - but I think our compiler can get rid of 90% of what we are throwing right now.
12:37:08
drmeister
Currently (block foo (let ((*special* ...)) ... (return-from foo ...) ...)) throws an exception.
12:38:25
drmeister
Currently I think Clasp's compiler budget is dominated by eclector because of this.
12:39:34
drmeister
That's not knocking eclector - it's a very common pattern. We need to compile it better.
12:40:04
drmeister
I think it's true in general. It's really hard to measure this. It's a "death by a thousand cuts".
12:41:35
scymtym
yeah, i see. i didn't take it as criticizing eclector. that said, i may have to look into performance issues at some point anyway
12:42:24
drmeister
I think something to keep in mind is "am I using the regular return path for the common case".
12:43:06
drmeister
Also, we have a tool now that lets us find the code that is doing the most throwing.
12:43:50
drmeister
In C++ it's really obvious when you are returning the normal way and when you are throwing an exception.
12:45:55
drmeister
Indeed ... the (block foo (let ((*special* ...)) ... (return-from foo ...) ...)) pattern currently throws because the return-from crosses a function boundary. Once Bike is done with it - it wont
12:48:24
drmeister
In that flame graph above - most of the time is lost throwing exceptions in eclector, cleavir and asdf.
12:53:21
scymtym
the combination of special variables and many embedded state machines (i.e. TAGBODY+GO/RETURN) is probably the main reason for this in eclector
14:55:23
Bike
Another ridiculous aspect of this is that the machinery that parses unwinding info is complex enough that some things could be better expressed with...... exceptions
14:57:44
Bike
drmeister: Since the thread local exception space won't include pointers to any Lisp objects, should I just use a regular thread-local variable instead of putting it in our thread local data structure gizmo?
14:59:44
Bike
well actually there's a bunch of non lisp things in there already, so now i'm not sure what it's for exactly
15:34:41
drmeister
Bike: If there are no pointers to lisp objects then you can put it in a thread-local variable - yes. That will save you an indirection.
15:35:18
drmeister
Everything accessible from my_thread->xxx requires following a pointer - but you can put lisp objects in the my_thread->xxx area.
15:37:41
drmeister
I'm keeping them both running until llvm10 or llvm11 when we can get rid of "object" if we choose.
15:38:22
drmeister
Bike: I just put them there - it didn't seem like a big deal. It would be better to put them somewhere else.
15:38:53
drmeister
https://github.com/clasp-developers/clasp/blob/dev/include/clasp/gctools/threadlocal.fwd.h#L79
15:39:21
drmeister
https://github.com/clasp-developers/clasp/blob/dev/include/clasp/gctools/threadlocal.h#L49
15:42:39
drmeister
I've made a point of keeping all the thread local stuff accessible through my_thread (ThreadLocalState*) and my_thread_low_level (ThreadLocalStateLowLevel*)
15:43:24
drmeister
It is - but when I started thread local storage support was still kind of squirrely - so I didn't want a lot of different thread local objects to deal with.
15:43:57
drmeister
Also, we need to store some Common Lisp pointers in the thread local storage. That is best done by allocating it at the top of the stack and letting the GC deal with it that way.
15:45:18
drmeister
So how about we move the POD/C++ objects from ThreadLocalState to ThreadLocalStateLowLevel and put them directly in thread local storage?
15:45:50
drmeister
It's real simple. We just move the field over and the compiler will complain about every my_thread->_foo access and we change it to my_thread_low_level._foo.
15:46:46
drmeister
Then we avoid an indirection and the GC doesn't have to scan these values and potentially confuse them with pointers. That's less of a problem in our 64-bit world.
15:48:03
drmeister
We can also take them out of ThreadLocalStateLowLevel entirely and have a bunch of thread local values.
15:48:23
Bike
means more #including, and having things only one system needs being stored in some random other file
15:48:52
Bike
I mean, look at the threadlocal structure now - it's just a potpourri of random things
15:49:00
drmeister
The ThreadLocalState struct for Common Lisp pointers is convenient for allocating it at the top of the stack (stack allocates down).
15:49:54
drmeister
But when I wasn't sure that I could put anything but a pointer in thread local storage - it made sense to have a 'god' object. Now it makes less sense.
15:53:55
drmeister
I can't tell you how much of a comfort my_thread->xxx is. I immediately know that it's thread local.
17:25:46
Bike
alright, so this isn't as stable as i thought, __cxa_begin_catch terminates when you try to quit sldb
17:26:56
Bike
because, i don't know, it needs to maintain a global stack of caught exceptions for whatever damn reason, and it can't do that with foreign exceptions
17:30:38
Bike
and it only can't handle foreign exceptions because the itanium abi design doesn't consider the possibility of catching a foreign exception in enough detail. they could have just had their own linked list of _Unwind_Exceptions, but no, they made the cxa exceptions list nodes themselves