It has been a while since I wrote anything, I have been busy with my new job that involves doing some interesting work on performance tuning. One of the challenges is to reduce object creation during the critical part of the application.

Garbage Collection hiccups has been a main pain point in java for some time, although java has improved over time the GC algorithms. Azul is a market leader developing pause-less GC but the Azul JVM is not free as speech!

Creating too many temporary/garbage objects doesn’t work too well because it creates work for the GC and it is going to have a negative effect on the latency. Too much garbage also doesn’t work well with multi-core system because it causes cache pollution.

So how should we fix this ?

Garbage less coding

This is only possible if you know how many objects you need upfront and pre-allocate them, but in reality this is very difficult to find. But even if you managed to do that, then you have to worry about another issue

  • You might not have enough memory to hold all the objects you need
  • You have to also handle concurrency

So what is the solution for the above problems

There is the Object Pool design pattern that can address both
of the above issues. It lets you to specify a number of objects that you need in a pool and handles concurrent requests to serve the requested objects.

Object Pool has been the base of many applications that have low latency requirements. A flavor of the object pool is the Flyweight design
pattern.

Both of the patterns above will help us in avoiding object creation. That is great so now GC work is reduced and in theory our application performance should improve. In practice, this doesn’t happen that way because Object Pool/Flyweight has to handle concurrency and whatever
advantage you get by avoiding object creation is lost because of concurrency issue.

What is the most common way to handle concurrency

Object pool is a typical producer/consumer problem and it can be solved by using the following techniques:

Synchronized: This was the only way to handle concurrency before JDK 1.5. Apache has written a wonderful object
pool
 API based on synchronized

Locks: Java added excellent support for concurrent programming after JDK 1.5. There has been some work to use Locks to develop Object Pool for eg furious-objectpool

Lock Free: I could not find any implementation that is built using fully lock free technique, but furious-objectpool uses
a mix ofArrayBlocking queue
ConcurrentLinked queue

Lets measure performance

In this test I have created a pool of 1 Million objects and those objects are accessed by a different pool implementation, objects are taken from the pool and returned back to the pool.

This test first starts with 1 thread and then the number of threads is increased to measure how the different pool implementations perform under contention

  • X Axis – No Of Threads
  • Y Axis – Time in Ms – Lower time is better

This test includes pools from Apache, Furious Pool & an ArrayBlocking based Pool

The Apache performed the worst and as the number of threads increases, performance degrades further. The reason is that the Apache pool is based on heavy use of “synchronized”

The other two, Furious & ArrayBlocking based pool performs better but both of them also slow down as contention increases.

ArrayBlocking queue based pool takes around 1000 ms for 1 Million items when 12 threads are trying to access the pool. Furious pool which internally uses Arrayblocking queue takes around 1975 ms for the same thing.

I have to do a more detailed investigation to find out why Furious is taking double time because it is also based on the ArrayBlocking queue.

Performance of arrayblocking queue is decent but it is a lock based approach. What type of performance do we get if we can implement lock free pool?

Lock free pool

Implementing lock free pool is not impossible but a bit difficult because you have to handle multiple producers & consumers.

I will implement a hybrid pool which will use lock on the producer side & non blocking technique on the consumer side.

Lets have a look at some numbers

I performed same test with new implementation (FastPool) and it is almost 30% faster than ArayBlocking queue.

30% improvement is not bad, it can definitely help us meet the latency goal.

What makes Fast Pool fast!

I used a couple of techniques to make it fast

  • Producers are lock based – Multiple producers are managed using locks, this is same as Array Blocking queue, so nothing great about this.
  • Immediate publication of released item – it publishes the element before the lock is released using cheap memory barrier. This gives some gain
  • Consumers are non blocking – CAS is used to achieve this, consumers are never blocked due to producers. Array Blocking queue blocks the consumer because it uses the same lock for the producer & the consumer
  • Thread Local to maintain value locality -  Thread Local is used to acquire the last value that was used, this reduces contention to a great extent.

If you are interested in having a look at code then it is available @ FastObjectPool.java

Reference: Lock Less
Java Object Pool
 from our JCG partner Ashkrit Sharma at the Are
you ready
 blog.

Lock Less Java Object Pool的更多相关文章

  1. 设计模式之美:Object Pool(对象池)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):实现 DatabaseConnectionPool 类. 实现方式(二):使用对象构造方法和预分配方式实现 ObjectPool ...

  2. java Object类学习

    /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETA ...

  3. Object Pool

    设计模式之美:Object Pool(对象池)   索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):实现 DatabaseConnectionPool 类. 意图 运用对象池化 ...

  4. java Object解析

    java Object是所有对象的根父类,所有对象都直接或间接集成自该类. java 的Object类也比较简单,有equals(Object).toString().finalize() java方 ...

  5. Java Object 引用传递和值传递

    Java Object 引用传递和值传递 @author ixenos Java没有引用传递: 除了在将参数传递给方法(或函数)的时候是"值传递",传递对象引用的副本,在任何用&q ...

  6. Java Object 构造方法的执行顺序

    Java Object 构造方法的执行顺序 @author ixenos 为了使用类而做的准备工作包括三个步骤 1)加载:类加载器查找字节码(一般在classpath中找),从字节码创建一个Class ...

  7. Java Object 对象创建的方式 [ 转载 ]

    Java Object 对象创建的方式 [ 转载 ] @author http://blog.csdn.net/mhmyqn/article/details/7943411 显式创建 有4种显式地创建 ...

  8. Java Object 对象拷贝答疑

    Java Object 对象拷贝答疑 @author ixenos 摘要:在对象的clone过程需要注意的几点.关于关键字this.super 关于clone[对象拷贝] 在实际编程过程,有时候我们会 ...

  9. Java Object 对象拷贝

    Java Object 对象拷贝 @author ixenos JAVA 对象拷贝 Java里的clone分为:  1.浅拷贝:浅复制仅仅复制所考虑的对象,而不复制它所引用的对象,Object类里的c ...

  10. .NET Core中Object Pool的简单使用

    前言 复用,是一个重要的话题,也是我们日常开发中经常遇到的,不可避免的问题. 举个最为简单,大家最为熟悉的例子,数据库连接池,就是复用数据库连接. 那么复用的意义在那里呢? 简单来说就是减少不必要的资 ...

随机推荐

  1. c++学习笔记(四):面向对象

    目录 类 & 对象 封装 访问权限 类的构造函数&析构函数 构造函数的分类及调用 拷贝构造函数的调用时机 构造函数调用规则 深拷贝与浅拷贝 初始化列表 类对象作为类成员 静态成员 C+ ...

  2. 北京智和信通受邀出席2022IT运维大会,荣获“2022智能运维星耀榜最具影响力企业”

    9月8日,由IT运维网.<网络安全和信息化>杂志社联合主办的"2022(第十三届)IT运维大会"在北京辽宁大厦成功举办.大会以"智慧先行,运维有术" ...

  3. 《Vue.js 设计与实现》读书笔记 - 第 4 章、响应系统的作用与实现

    第 4 章.响应系统的作用与实现 4.1 响应式数据与副作用 副作用函数就是会对外部造成影响的函数,比如修改了全局变量. 响应式:修改了某个值的时候,某个会读取该值的副作用函数能够自动重新执行. 4. ...

  4. 在C#中使用适配器Adapter模式和扩展方法解决面向的对象设计问题

    之前有阵子在业余时间拓展自己的一个游戏框架,结果在实现的过程中发现一个设计问题.这个游戏框架基于MonoGame实现,在MonoGame中,所有的材质渲染(Texture Rendering)都是通过 ...

  5. 利用3D标签,生成RLE标签编码,并保存到csv文件

    # coding:utf-8from glob import globimport osimport SimpleITK as sitkfrom pathlib import Pathimport n ...

  6. iOS中UIlabel多行文本展示使用小结

    最近在项目开发中遇到了一个新的需求,就是菜单标题最多两行展示,一行展示的标签顶部和两行展示的标签顶部对齐.看到要求后,第一反应是这是什么奇葩的设计,但是没办法谁让别人是产品经理呢.细细思索后,代码如下 ...

  7. kotlin协程——>基础、取消与超时

    Kotlin使用挂起函数为异步操作,使用kotlinx.coroutines中的launch.async 1. 第⼀个协程程序 import kotlinx.coroutines.* fun main ...

  8. 云原生周刊:K8s 的 YAML 技巧 | 2023.12.4

    开源项目推荐 Helmfile Helmfile 是用于部署 Helm Chart 的声明性规范.其功能有: 保留图表值文件的目录并维护版本控制中的更改. 将 CI/CD 应用于配置更改. 定期同步以 ...

  9. KubeSphere 社区双周报 | Fluent Operator 发布 v2.5.0 | 2023.09.01-09.14

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  10. 使用 KubeSphere 部署高可用 RocketMQ 集群

    作者:老Z,云原生爱好者,目前专注于云原生运维,KubeSphere Ambassador. Spring Cloud Alibaba 全家桶之 RocketMQ 是一款典型的分布式架构下的消息中间件 ...