对JVM的NUMA认识
我的问题涉及JVM应用程序可以利用主机的NUMA布局的程度。对JVM的NUMA认识
我有一个Akka应用程序,其中参与者通过将传入数据与已加载到不可变(Scala)对象的“通用”数据进行组合来并发处理请求。该应用可以在云中很好地扩展,使用许多双核虚拟机,但在单个64核心机器上执行效果不佳。我认为这是因为公共数据对象驻留在一个NUMA单元中,并且从其他单元并发访问的许多线程对于互连而言太多。
如果我运行64个单独的JVM应用程序,每个应用程序包含1个actor,那么性能会很好。一个更温和的方法可能是运行尽可能多的JVM应用程序,因为有NUMA单元(我的情况是8个),给主机操作系统一个保持线程和内存在一起的机会?
但是,在单个JVM中实现相同效果还有更明智的方法吗?例如。如果我用一个case类的几个实例替换了我的公共数据对象,那么JVM是否有能力将它们放在最佳的NUMA单元上?
更新:
我使用Oracle JDK 1.7.0_05和阿卡2.1.4
现在我已经试图与UseNUMA和UseParallelGC JVM选项。在使用一个或几个JVM时,对性能下降似乎没有任何显着影响。我也试过用PinnedDispatcher和thre-pool-executor没有任何作用。我不确定配置是否有效,因为在启动日志中似乎没有什么不同。
当我每个工人使用一个JVM(〜50)时,最大的改进仍然存在。然而,这个问题似乎是在FailureDector注册Akka集群JVM之间的“第一次心跳”成功交换之前存在长时间延迟(长达几分钟)。我怀疑还有其他一些问题,我还没有发现。自从我达到默认的最大进程数(1024)以来,我不得不增加ulimit -u。
只是为了澄清,我并没有试图实现大量的消息,只是试图让很多独立的角色同时访问一个不可变的对象。
我想如果你确定问题不在消息处理算法中,那么你应该考虑到不仅NUMA选项,而且整个环境。配置,从JVM版本开始(最新版本更好,Oracle JDK也主要比OpenJDK更好),然后选择JVM选项(包括GC,内存,并发选项等),然后选择Scala和Akka版本(最新版本的候选版本和里程碑版本会更好)还有Akka配置。
从here你可以借用所有重要的事情得到50M messages per second of total throughput for Akka actors on contemporary laptops。
从来没有机会在64核心服务器上运行这些基准 - 所以任何反馈都将不胜感激。
根据我的发现,当池中的线程数量增加时,ForkJoinPool
的当前实现会增加消息发送延迟。对于参与者之间的响应请求呼叫率很高的情况来说,这是非常明显的。 G。在我的笔记本电脑中,当将池大小从4增加到64时,对于这种情况,Akka演员的消息发送延迟增长到多数执行程序服务(Scala的ForkJoinPool
,JDK的ForkJoinPool
,ThreadPoolExecutor
)的2-3倍。
您可以通过运行mvnAll.sh
并将benchmark.parallelism
系统变量设置为不同的值来检查是否有任何差异。
下面是一篇博客文章,介绍我们的48核心测试服务器上使用FJP的akka可伸缩性配置文件:http://letitcrash.com/post/20397701710/50-million-messages-per-second-on-a-single-machine –
您是否在使用-XX:+ UseNUMA jvm选项? – cmbaxter
另外,您使用的是什么GC设置?什么执行器配置? –
您可能需要告诉akka使用更好的线程模式,请参阅此处获取某些邮箱配置选项:http://doc.akka.io/docs/akka/snapshot/scala/dispatchers.html – Noah