是否存在用Java编写低延迟代码的特定于Java的技术(不适用于C ++的技术)?我经常看到Java低延迟角色,并且他们要求获得编写低延迟Java的经验-有时似乎有点矛盾。
我唯一能想到的就是JNI的经验,将I / O调用外包给本地代码。也可能使用破坏者模式,但这不是实际技术。
有编写低延迟代码的Java特定技巧吗?
我知道有一个实时Java规范,但是我被警告实时与低延迟不一样。
是否存在用Java编写低延迟代码的特定于Java的技术(不适用于C ++的技术)?我经常看到Java低延迟角色,并且他们要求获得编写低延迟Java的经验-有时似乎有点矛盾。
我唯一能想到的就是JNI的经验,将I / O调用外包给本地代码。也可能使用破坏者模式,但这不是实际技术。
有编写低延迟代码的Java特定技巧吗?
我知道有一个实时Java规范,但是我被警告实时与低延迟不一样。
Answers:
除了Martijn的评论外,我还要添加:
预热您的JVM。字节码开始于为Hotspot解释,然后在观察10K后在服务器上进行编译。分层编译可以是一个很好的止步差距。
类加载是一个顺序过程,涉及到磁盘的IO。确保主要交易流的所有类均已预先加载,并且永不从烫发一代中逐出。
遵循“ 单一作者原则 ”,避免争夺利特尔定律及其对排队效应的影响,此外,还应研究阿姆达尔定律,以了解哪些是平行的,是否值得。
为您的业务领域建模,并确保所有算法均为O(1)或至少为O(log n)。根据我的经验,这可能是导致性能问题的最大原因。确保进行性能测试以涵盖主要情况。
Java中的低延迟不仅限于Java。您需要了解执行代码的整个堆栈。这将涉及操作系统调整,选择适当的硬件,调整系统软件以及该硬件的设备驱动程序。
现实点。如果您需要低延迟,请不要在管理程序上运行。确保对于需要处于可运行状态的所有线程具有足够的核心。
高速缓存未命中是您最大的性能损失。使用对缓存友好的算法,并通过任务集或numactl(对于JVM)或JNI(对于单个线程)来设置对处理器核心的相似性。
考虑替代的JVM,例如Azul的Zing和无暂停垃圾收集器。
最重要的是让某人参与经验。从长远来看,这将为您节省大量时间。无耻的插头:-)
实时和低延迟是明显不同的主题,尽管它们经常相关。实时要比快速更可预测。以我的经验,实时JVM甚至是软实时JVM都比普通JVM慢。
有很多事情需要注意。我目前在克里特岛的网络访问受到限制,因此(相当)简短。另外,我不是低延迟专家,但是我的一些同事在现实生活中扮演着一个:-)。
您需要欣赏“机械同情”(Martin Thompson创造的一个术语)。换句话说,您需要了解底层硬件在做什么。了解CPU如何加载高速缓存行,它们的读/写带宽是多少,主内存的速度等等,是非常重要的。为什么?因为您需要推理Java源代码如何通过运行时JVM影响操作系统/硬件。例如,字段变量在源代码中的布局方式会导致高速缓存行逐出(花费您大约150个时钟周期),hmmm ... :-)。
通常,您需要无锁算法和I / O。即使是设计最完善的并发应用程序(使用锁)也有被阻塞的风险,以低延迟进行阻塞通常很糟糕:-)。
了解对象分配和垃圾回收。这是一个很大的话题,但是基本上您想避免GC暂停(通常是由各种GC集合的Stop the World特性引起的)。像Azul收集器这样的专业GC收集器在许多情况下都可以为您提供开箱即用的解决方案,但是对于大多数人来说,他们需要了解如何调整Sun / Oracle GC(CMS,G1等)。
热点JIT令人惊讶。了解有关它的优化的知识,但总的来说,所有好的OO技术(封装,小的方法,尽可能多的不可变数据)都将使JIT进行优化,从而为您提供精心制作的C / C ++代码可以为您提供的各种性能水平。
整体系统架构。请注意网络,如何在同一位置放置机器,是否通过光纤等连接到交换机等。
请注意日志记录的影响。记录二进制文件或使用可以离线解析的编码输出可能是一个好主意。
总体而言,我强烈建议您参加Kirk Pepperdine的Java Performance Tuning课程 [免责声明:我自己教这门课程,所以我有偏见]。您将很好地了解JVM的各个方面及其对基础O / S和硬件的影响。
PS:我稍后会尝试重新整理并整理一下。