思路
CRR是框架的性能热点,会频繁创建和销毁Map对象,优化后收益较高。
captured 数据和 backup 数据中,ThreadLocal及其子类作为key使用,由于 ThreadLocal 为 ref identity,使用 IdentityHashMap 更优。
优化策略
- 使用IdentityHashMap替代HashMap,基于System.identityHashCode(), 使用==进行键比较,更高效的容量管理,内存占用大约减少一半,使用线性探索法局部性更好,查询性能更好。IdentityHashMap 支持 null key、null value
- 新增工厂方法newIdentityHashMap()
- 接口改用Map抽象 (向后兼容)
- 内部优化 (对用户无影响)
WeakHashMap为什么不改?
WeakHashMap提供弱引用语义,用于自动清理弱可达的 key 及其 entry。IdentityHashMap不支持弱引用,改不了。
涉及修改
风险
如果 TTL 子类重写了equals和 hashcode 方法,会导致意想不到的问题。实际上,TTL作为Map的key时,其identity就是ref identity,应该禁止子类重写 equals和 hashcode 方法。
代码示例
修改前
private static class TtlTransmittee implements Transmittee<HashMap<TransmittableThreadLocal<Object>, Object>, HashMap<TransmittableThreadLocal<Object>, Object>> {
@NonNull
@Override
public HashMap<TransmittableThreadLocal<Object>, Object> capture() {
final HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value = newHashMap(holder.get().size());
for (TransmittableThreadLocal<Object> threadLocal : holder.get().keySet()) {
ttl2Value.put(threadLocal, threadLocal.getTransmitteeValue());
}
return ttl2Value;
}
}
修改后
private static class TtlTransmittee implements Transmittee<Map<TransmittableThreadLocal<Object>, Object>, Map<TransmittableThreadLocal<Object>, Object>> {
@NonNull
@Override
public Map<TransmittableThreadLocal<Object>, Object> capture() {
final Map<TransmittableThreadLocal<Object>, Object> ttl2Value = newIdentityHashMap(holder.get().size());
for (TransmittableThreadLocal<Object> threadLocal : holder.get().keySet()) {
ttl2Value.put(threadLocal, threadLocal.getTransmitteeValue());
}
return ttl2Value;
}
}
参考
思路
CRR是框架的性能热点,会频繁创建和销毁Map对象,优化后收益较高。
captured 数据和 backup 数据中,ThreadLocal及其子类作为key使用,由于 ThreadLocal 为 ref identity,使用 IdentityHashMap 更优。
优化策略
WeakHashMap为什么不改?
WeakHashMap提供弱引用语义,用于自动清理弱可达的 key 及其 entry。IdentityHashMap不支持弱引用,改不了。
涉及修改
风险
如果 TTL 子类重写了equals和 hashcode 方法,会导致意想不到的问题。实际上,TTL作为Map的key时,其identity就是ref identity,应该禁止子类重写 equals和 hashcode 方法。
代码示例
修改前
修改后
参考