Skip to content

优化CtSph#lookProcessChain 创建拦截链方法(减少第一次创建拦截链持有锁占用时间,提升rt,减少gc压力) #3513

@LilMosey

Description

@LilMosey

原逻辑:

Image

chainMap 是一个 volatile 修饰的 Map。首次获取 ProcessorSlotChain 时,如果为空,旧逻辑会进入同步块,new 一个新的 map,并通过 putAll 拷贝原有数据后再新增,最终整体替换 chainMap,利用 volatile 替换引用实现可见性。

优化后:

Image
新逻辑为在同步块中直接put。(synchronized本身保证可见性)

好处:

1: 提高rt:
避免在高并发下频繁进行 putAll 拷贝,特别是在 map 较大(如含有数百个资源)的情况下,putAll花费的时间越多,优化可以减少锁占用时间,从而提高rt。

2: 减少GC压力:
直接put无需频繁创建大量短生命周期的临时 map,降低内存占用和 GC 负担。

理由:
看了整个代码后,发现真正使用chainMap的地方也只有lookProcessChain这一个方法,其余的方法比如resetChainMap、getChainMap是default修饰的,仅仅用于测试调用,只能在当前包调用,所以这里我没有加synchronized。而entrySize方法是一个public修饰的方法,为了保证其可见性,我使用了synchronized关键字。

synchronized关键字本身通过内存屏障保证了可见性,因此chainMap不需要加volatile关键字修饰。

类似的实现比如java中的Collections.synchronizedMap()。
Image

后续思考:

Image

当资源数限制(如 6000)放开后,或者可以允许超一点点去追求极致的性能的话,代码还可以进行如下优化:

chainMap使用ConcurrentHashMap,不需要显示进行加锁,直接采用ConcurrentHashMap#computeIfAbsent方法,这样锁的粒度更小,性能更好。

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions