-
Enhancement
-
Resolution: Fixed
-
P4
-
16.0.1
-
b25
-
generic
-
generic
Reflection method is firstly invoked with JNI, after invocation count exceeds threshold specific GeneratedMethodAccessor is created to optimize invocation speed.
In current implementation, there is no lock/synchornization between multiple threads create same GeneratedMethodAccessor in same NativeMethodAccessorImpl object. Multiple GeneratedMethodAccessor could be created spontanously, this wastes CPU and multiple creations could cause a lot contention in runtime define_instance_class.
Above scenario could be happened when using protobuf generated classes at startup phase, especially with option "optimize_for = CODE_SIZE". Multiple threads invoke same reflect methods to send/receive data at startup time. Redudant GeneratedMethodAccessor creations cause startup slow and most time is spent in runtime define_instance_class lock contention.
Attached is a simplied testcase, create 10k reflection methods and invoked in 100 threads. On 8 core linux X86, avoid duplicated GeneratedMethodAccessor reduce runtime from 12s to < 1.5s.
In current implementation, there is no lock/synchornization between multiple threads create same GeneratedMethodAccessor in same NativeMethodAccessorImpl object. Multiple GeneratedMethodAccessor could be created spontanously, this wastes CPU and multiple creations could cause a lot contention in runtime define_instance_class.
Above scenario could be happened when using protobuf generated classes at startup phase, especially with option "optimize_for = CODE_SIZE". Multiple threads invoke same reflect methods to send/receive data at startup time. Redudant GeneratedMethodAccessor creations cause startup slow and most time is spent in runtime define_instance_class lock contention.
Attached is a simplied testcase, create 10k reflection methods and invoked in 100 threads. On 8 core linux X86, avoid duplicated GeneratedMethodAccessor reduce runtime from 12s to < 1.5s.