Skip to content

dreamlike-ocean/StableValue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

两种可行高性能惰性单例的实现

invokdynamic

已知 invokedynamic是线程安全的,MethodHandles.constant支持MH返回一个常量,那么结合起来如何呢?

java.lang.Class中存在一个特殊的字段classData可以用于存放和这个类相关联的一个对象,当我们定一个hidden class时使用lookup.defineHiddenClassWithClassData(classByteCode, factory, false)即可对其进行赋值,当方法执行到对应的invokedynamic时我们使用MethodHandles.classData(lookup, DEFAULT_NAME, Supplier.class)再将其取出来,包裹下变成ConstantCallSite返回即可

ConstantDynamic

ConstantDynamic是一个特殊的字节码,其储存在常量池中,当被load到栈顶时会执行BootstrapMethod,然后被jit将返回值缓存起来,之后再次调用时直接返回缓存的值,这个特性正好可以用于实现高性能的懒加载单例。

具体可以参考JEP 309: Dynamic Class-File Constants 以及 hands-on-java-constantdynamic

实现细节

请参考issue的讨论

benchmark

可以执行下面的命令进行benchmark

sh ./benchmark.sh

在我本人的机子上可以跑出来如下结果

并发线程数目为5
stableValue.Benchmark.StableValueBenchmarkCase.testClassInit            thrpt   10  2900813.932 ± 26353.332  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testDCL                  thrpt   10   210772.581 ±  2527.113  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testIndyStabValue        thrpt   10  2902634.437 ± 25928.781  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testIndyStabValueCody    thrpt   10  2902663.558 ± 23987.111  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testIndyStabValueHidden  thrpt   10  2900383.951 ± 24068.082  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testJdkStableValue       thrpt   10  2892260.871 ± 45261.131  ops/s
stableValue.Benchmark.StableValueBenchmarkCase.testPlain                thrpt   10  2918079.807 ±  4314.742  ops/s


About

使用invokedynamic实现的零依赖StableValue用于取代DCL模式

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published