Synchronize variable reification against real class.#5919
Synchronize variable reification against real class.#5919enebo merged 2 commits intojruby:masterfrom
Conversation
This is likely at least a partial fix for jruby#5910, where it appears that multiple threads all trigger reificatin of a class's variables at the same time, leading to some of those threads choosing a different reified type and ultimately class casting exceptions. The change here synchronizes against the class's "real" class, which should be the one on which we attach the allocated. This should force multiple threads all allocating the first instance at once to wait for each other, eventually falling back on the new allocator that does not re-reify the type. This will eventually be moot once individual object instances hold a reference to their own layout managers.
cb4812e to
1385578
Compare
|
looks reasonable (given no further details #5910 - still weird that there's only one pathological case). would it make sense to reduce the lock duration to the bare minimum of (double-checking) and setting the generated class-and-allocator?, moving 'only' these parts under the critical section: https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/specialized/RubyObjectSpecializer.java#L152-L153 |
enebo
left a comment
There was a problem hiding this comment.
I am pretty interested in seeing how much lock contention this ends up bringing into the mix. Allocating the same type at the same time across Rails threads seems like it will be common. If we can notice the impact then perhaps as kares says we can shorten the lock somehow? Or perhaps it is just the price we have to pay?
Secondly, I would like to make sure this fixes the original reporters problem before putting out 9.2.9 assuming they can test it without too much trouble.
|
I have been pondering impact of this and I believe the ordinary classes will not be much of an impact because there are just not that many types in a typical application. A few thousand locks when most happen early in an app does not seem like a big deal. Singleton types perhaps in some DCI pattern? Two threads singletonizing the same object at the same time already hurts my head. We must already synch on that? Trying to think of patterns where a framework would endlessly make new types. Seems like the main worry to more locking here. |
The only thing that could move out would be the walking of all classes and methods in the type's hierarchy. Seems like that should be ok; the structures involved are all safe. |
* Synchronize only around the reification and assignment of the new allocator, to limit contention. * Move all code-walking logic into IRMethod. * Improve code-walking logic to walk AST if present rather than forcing code to compile.
|
It turns out that the related Ruby code in #5910 was actually buggy to begin with; it allowed uninitialized classes to be constructed, which led to us seeing multiple views of instance variables in defined methods. I've detailed that here: #5910 (comment) We can't fix that, but it did expose some weaknesses in our variable reification that I have fixed in the most recent commit:
|
This is likely at least a partial fix for #5910, where it appears
that multiple threads all trigger reificatin of a class's
variables at the same time, leading to some of those threads
choosing a different reified type and ultimately class casting
exceptions.
The change here synchronizes against the class's "real" class,
which should be the one on which we attach the allocated. This
should force multiple threads all allocating the first instance
at once to wait for each other, eventually falling back on the
new allocator that does not re-reify the type.
This will eventually be moot once individual object instances hold
a reference to their own layout managers.