Akka actor消息需要内存池
Akka actor message needs memory pool
我是 java 的新人。我是 c++ 程序员,现在学习 java 两个月。
对不起我的台球英语。
我有一个问题,Akka actor 模型是否需要内存池或对象池。我想如果我从一个演员向另一个演员发送一些消息,我必须分配一些堆内存(就像新的一些字符串,或者新的一些 BigInteger 等等......)而且时间,垃圾收集器将是开始了(我不确定它是否会开始)并且它使我的应用程序计算缓慢。
所以我搜索了创建内存池的方法,但失败了(Java 不支持内存池)。我可以创建对象池,但在其他项目中我没有发现任何人将对象池与 actor(也在 Akka 主页中)一起使用。
akka主页上有关于这个主题的文档吗?请告诉我 link 或告诉我问题的解决方案。
谢谢。
使用 ArrayBlockingQueue 来保存对象池应该有所帮助,
这是示例代码。
创建池并在其中插入池对象的实例。
BlockingQueue<YOURCLASS> queue = new ArrayBlockingQueue<YOURCLASS>(256);//Adjust 256 to your desired count. ArrayBlockingQueues size cannot be adjusted once it is initialized.
queue.put(YOUROBJ); //This should be in your code that instanciates the pool
以及稍后您需要的地方(在接收消息的 actor 中)
YOURCLASS instanceName = queue.take();
您可能需要为此编写一些代码来创建和管理池。
但这就是它的要点。
如果您很可能会在多台计算机上使用 Akka,则消息会在线上序列化并发送到另一个实例。这意味着仅仅一个本地内存池是不够的。
虽然从技术上讲,您可以编写自定义 JSerializer(请参阅文档 here)实现,在反序列化后将本地消息存储在内存池中,但我觉得这对大多数应用程序来说有点矫枉过正(并且容易搞砸,实际上会随着地图中的查找时间而恶化性能)
是的,当 GC 启动时,应用程序在高负载下会有点滞后。但是在95%的场景下,尤其是在像Akka这样的高性能框架下,GC不会成为你的瓶颈:IO会。
我并不是说你不应该这样做。我是说,在你接受这项任务之前,考虑到它的重要性,你应该 衡量 GC 在运行时对你的应用程序的影响,比如 Kamon 或其他 Akka 专门监控解决方案,只有在您确定值得之后才可以去做。
可以进行对象池化以最小化长尾延迟(通过牺牲多线程环境中的中位数)。考虑使用适当的队列,例如来自 JCTools、Distruptor 或 Agrona。不要忘记使用存储对象中的多个读取通过可变状态进行状态交换的参与规则 - https://youtu.be/nhYIEqt-jvY(我能找到的最佳内容)。
同样,不要指望在使用这种稍微危险的技术的过程中有所改进。您将失去 L1-L3 缓存效率,并使用障碍礼貌 PCI。
有点切线(了解低延迟技术):
如果你想坚持使用 Akka,或者使用自定义反应模型,其中对象池由单线程使用,或者复制内存,那么你可能会考虑一些具有较低延迟的 GC 实现。干扰者的方法。
另一种选择是使用内存区域(Erlang VM 的工作方式)。它会产生垃圾,但形式很容易被 GC 处理!
如果您采用非常低延迟的 IO 并且是延迟的最大敌人 - 忘记传统 TCP(与 Infininiband 上的 RDMA 相比)、交换机(通过无交换机)、OS 通过 OS 访问磁盘调用和文件系统(使用 RDMA),忘记由同一个核心共享的中断,而不是固定核心(并且没有旋转输入)到真正的 CPU 核心(vs virtual/hyperthreads)或 NUMA 间通信或消息一个而不是多个消费者的硬件多播(或更好的光开关)并且不要忘记为 JVM 启用 Epsilon GC ;)
我是 java 的新人。我是 c++ 程序员,现在学习 java 两个月。 对不起我的台球英语。
我有一个问题,Akka actor 模型是否需要内存池或对象池。我想如果我从一个演员向另一个演员发送一些消息,我必须分配一些堆内存(就像新的一些字符串,或者新的一些 BigInteger 等等......)而且时间,垃圾收集器将是开始了(我不确定它是否会开始)并且它使我的应用程序计算缓慢。
所以我搜索了创建内存池的方法,但失败了(Java 不支持内存池)。我可以创建对象池,但在其他项目中我没有发现任何人将对象池与 actor(也在 Akka 主页中)一起使用。
akka主页上有关于这个主题的文档吗?请告诉我 link 或告诉我问题的解决方案。
谢谢。
使用 ArrayBlockingQueue 来保存对象池应该有所帮助,
这是示例代码。
创建池并在其中插入池对象的实例。
BlockingQueue<YOURCLASS> queue = new ArrayBlockingQueue<YOURCLASS>(256);//Adjust 256 to your desired count. ArrayBlockingQueues size cannot be adjusted once it is initialized.
queue.put(YOUROBJ); //This should be in your code that instanciates the pool
以及稍后您需要的地方(在接收消息的 actor 中)
YOURCLASS instanceName = queue.take();
您可能需要为此编写一些代码来创建和管理池。 但这就是它的要点。
如果您很可能会在多台计算机上使用 Akka,则消息会在线上序列化并发送到另一个实例。这意味着仅仅一个本地内存池是不够的。
虽然从技术上讲,您可以编写自定义 JSerializer(请参阅文档 here)实现,在反序列化后将本地消息存储在内存池中,但我觉得这对大多数应用程序来说有点矫枉过正(并且容易搞砸,实际上会随着地图中的查找时间而恶化性能)
是的,当 GC 启动时,应用程序在高负载下会有点滞后。但是在95%的场景下,尤其是在像Akka这样的高性能框架下,GC不会成为你的瓶颈:IO会。
我并不是说你不应该这样做。我是说,在你接受这项任务之前,考虑到它的重要性,你应该 衡量 GC 在运行时对你的应用程序的影响,比如 Kamon 或其他 Akka 专门监控解决方案,只有在您确定值得之后才可以去做。
可以进行对象池化以最小化长尾延迟(通过牺牲多线程环境中的中位数)。考虑使用适当的队列,例如来自 JCTools、Distruptor 或 Agrona。不要忘记使用存储对象中的多个读取通过可变状态进行状态交换的参与规则 - https://youtu.be/nhYIEqt-jvY(我能找到的最佳内容)。
同样,不要指望在使用这种稍微危险的技术的过程中有所改进。您将失去 L1-L3 缓存效率,并使用障碍礼貌 PCI。
有点切线(了解低延迟技术): 如果你想坚持使用 Akka,或者使用自定义反应模型,其中对象池由单线程使用,或者复制内存,那么你可能会考虑一些具有较低延迟的 GC 实现。干扰者的方法。 另一种选择是使用内存区域(Erlang VM 的工作方式)。它会产生垃圾,但形式很容易被 GC 处理!
如果您采用非常低延迟的 IO 并且是延迟的最大敌人 - 忘记传统 TCP(与 Infininiband 上的 RDMA 相比)、交换机(通过无交换机)、OS 通过 OS 访问磁盘调用和文件系统(使用 RDMA),忘记由同一个核心共享的中断,而不是固定核心(并且没有旋转输入)到真正的 CPU 核心(vs virtual/hyperthreads)或 NUMA 间通信或消息一个而不是多个消费者的硬件多播(或更好的光开关)并且不要忘记为 JVM 启用 Epsilon GC ;)