- 在应用程序中,我们有大约 30 种重复创建的对象。
- 它们有些生命周期长(小时),有些生命周期短(毫秒)。
- 对象可以在一个线程中创建并在另一个线程中销毁。
有没有人知道在最小创建/销毁延迟、低锁争用和合理内存利用率方面什么是好的池化技术?
追加 1.
1.1。一种类型的对象池/内存分配通常与另一种类型无关(异常(exception)情况见 1.3)
1.2。一次只为一种类型(类)执行内存分配,通常一次为多个对象执行。
1.3。如果一个类型使用指针聚合另一个类型(出于某种原因),这些类型将一起分配到一 block 连续的内存中。
追加 2.
2.1。众所周知,使用按类型访问序列化的集合比新建/删除更糟糕。
2.2。应用程序在不同的平台/编译器上使用,不能使用特定于编译器/平台的技巧。
追加 3.
显而易见,最快(延迟最低)的实现应该将对象池组织为星型工厂网络。对于其他线程特定工厂,中央工厂是全局的。常规对象提供/回收在线程特定工厂中更有效,而中央工厂可用于线程之间的对象平衡。
3.1。组织中央工厂和线程特定工厂之间通信的最有效方式是什么?
最佳答案
我假设您在完成所有创建后已经分析并测量了您的代码,并确认创建/销毁确实导致了问题。否则,这是您首先应该做的。
如果您仍想进行对象池化,作为第一步,您应该确保您的对象是无状态的,因为这是重用对象的先决条件。同样,您应该确保对象的成员和对象本身没有问题,可以从创建它的线程以外的其他线程使用。 (COM STA 对象/窗口句柄等)
如果您使用 Windows 和 COM,使用系统提供的池的一种方法是编写自由线程对象并启用对象池,这将使 COM+ 运行时(以前称为 MTS)为您执行此操作。如果您使用 Java 等其他平台,您可能会使用定义对象应实现的接口(interface)的应用程序服务器,而 COM+ 服务器可以为您进行池化。
或者您可以推出自己的代码。但是你应该尝试找出是否有这种模式,如果有,请使用它而不是下面的内容
如果您需要滚动自己的代码,请创建一个可动态增长的集合来跟踪已创建的对象。最好对集合使用 vector ,因为您只会将其添加到集合中,并且很容易遍历它以搜索空闲对象。 (假设您不删除池中的对象)。根据您的删除策略更改集合类型(如果您使用 C++,则指向对象的指针/引用 vector ,以便在同一位置删除和重新创建对象)
每个对象都应该使用一个标志进行跟踪,该标志可以以易变的方式读取,并使用互锁功能进行更改以将其标记为已使用/未使用。
如果使用所有对象,则需要创建一个新对象并将其添加到集合中。在添加之前,您可以获取锁(临界区),将新对象标记为正在使用并退出锁。
测量并继续 - 如果您将上述集合实现为一个类,您可能可以轻松地为不同的对象类型创建不同的集合,从而减少执行不同工作的线程的锁争用。
最后你可以实现一个重载的类工厂接口(interface),它可以创建各种池化对象并知道哪个集合拥有哪个类
然后您可以从那里优化此设计。
希望对您有所帮助。
关于c++ - 多线程应用程序中的最小延迟对象池技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/99907/