0

我是java新手。我是 C++ 程序员,现在学习 java 2 个月。对不起我的泳池英语。

我有一个问题,如果它需要 Akka 演员模型的内存池或对象池。我想如果我从一个演员向其他演员之一发送一些消息,我必须分配一些堆内存(就像 new Some String 或 new Some BigInteger 等等..)而且随着时间的推移,垃圾收集器将开始了(我不确定它是否会启动),它使我的应用程序计算缓慢。

所以我寻找制作内存池的方法并失败(Java不支持内存池)。而且我可以制作对象池,但在其他项目中,我没有发现有人将对象池与演员一起使用(也在 Akka 主页中)。

akka 主页中是否有关于此主题的任何文档?请告诉我链接或告诉我问题的解决方案。

谢谢。

4

3 回答 3

1

如果您可能会在多台计算机上使用 Akka,则消息会在线上序列化并发送到另一个实例。这意味着仅仅一个本地内存池是不够的。

虽然从技术上讲,您可以编写一个自定义 JSerializer(请参阅此处的文档)实现,在反序列化后将本地消息存储在内存池中,但我觉得这对于大多数应用程序来说有点矫枉过正(而且很容易发生故障并实际上恶化性能与地图中的查找时间)

是的,当 GC 启动时,应用程序在重负载下会有点滞后。但在 95% 的场景中,尤其是在像 Akka 这样的高性能框架下,GC 不会成为你的瓶颈:IO 会。

我不是说你不应该这样做。我的意思是,在你接受这个任务之前,考虑到它的重要性,你应该在运行时使用 Kamon 或其他 Akka 专用监控解决方案来衡量GC 对你的应用程序的影响,并且只有在你确定它值得之后你可以去做。

于 2017-05-18T09:32:20.947 回答
0

使用 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

稍后在您需要它的地方(在接收消息的演员中)

YOURCLASS instanceName = queue.take();

您可能必须围绕此编写一些代码来创建和管理池。但这就是它的要点。

于 2017-05-18T08:51:24.080 回答
0

可以进行对象池以最小化延迟的长尾(通过在多线程环境中牺牲中值)。考虑使用适当的队列,例如来自 JCTools、Distruptor 或 Agrona。不要忘记使用存储对象中的多个读取通过可变状态进行状态交换的参与规则 - https://youtu.be/nhYIEqt-jvY(我能找到的最佳内容)。

同样,不要指望使用这种稍微危险的技术在整个过程中有所改善。您将失去 L1-L3 缓存效率,并且会使用屏障来礼貌 PCI。

切线一点(以了解低延迟技术):如果您想坚持使用 Akka,可以考虑一些具有较低延迟的 GC 实现,或者使用自定义反应模型,其中对象池由单线程使用,或者内存复制到例如 Distrupptor 的方法。另一种选择是使用内存区域(Erlang VM 的工作方式)。它会产生垃圾,但形式很容易被 GC 处理!

如果您使用非常低延迟的 IO 并且是延迟的最大敌人 - 忘记传统 TCP(与 Infininiband 上的 RDMA 相比)、交换机(通过 swichless)、操作系统通过操作系统调用和文件系统访问磁盘(使用 RDMA),忘记共享的中断相同的核心,而不是固定核心(并且没有旋转输入)到真正的 CPU 核心(与虚拟/超线程)或 NUMA 之间的通信或消息一一而不是硬件多播(或更好的光开关)用于多个消费者,不要忘记为 JVM 转 Epsilon GC ;)

于 2020-10-21T03:46:34.983 回答