我应该尽量避免使用“new”吗?关键词超低延迟软件

本文关键字:关键词 软件 延迟 new 我应该 | 更新日期: 2023-09-27 17:51:11

我在写高频交易软件。我真的在乎每一微秒。现在它是用c#写的,但我很快就会迁移到c++。

让我们考虑这样的代码

// Original
class Foo {
....
    // method is called from one thread only so no need to be thread-safe
    public void FrequentlyCalledMethod() {
        var actions = new List<Action>();
        for (int i = 0; i < 10; i++) {
            actions.Add(new Action(....));
        }
        // use actions, synchronous
        executor.Execute(actions);
        // now actions can be deleted
    }

我猜超低延迟软件不应该过多地使用"new"关键字,所以我将actions移到一个字段:

// Version 1
class Foo {
....
    private List<Action> actions = new List<Action>();
    // method is called from one thread only so no need to be thread-safe
    public void FrequentlyCalledMethod() {
        actions.Clear()
        for (int i = 0; i < 10; i++) {
            actions.Add(new Action { type = ActionType.AddOrder; price = 100 + i; });
        }
        // use actions, synchronous
        executor.Execute(actions);
        // now actions can be deleted
    }

也许我应该尽量避免使用"new"关键字?我可以使用一些预分配对象的"池":

// Version 2
class Foo {
....
    private List<Action> actions = new List<Action>();
    private Action[] actionPool = new Action[10];
    // method is called from one thread only so no need to be thread-safe
    public void FrequentlyCalledMethod() {
        actions.Clear()
        for (int i = 0; i < 10; i++) {
            var action = actionsPool[i];
            action.type = ActionType.AddOrder;
            action.price = 100 + i;
            actions.Add(action);
        }
        // use actions, synchronous
        executor.Execute(actions);
        // now actions can be deleted
    }
  • 我应该走多远?
  • 避免new有多重要?
  • 我会赢得任何东西,而使用预分配的对象,我只需要配置?(如上图所示)

请注意,这是超低延迟,所以让我们假设性能优先于可读性,可维护性等。

我应该尽量避免使用“new”吗?关键词超低延迟软件

在c++中,您不需要new来创建具有有限作用域的对象。

void FrequentlyCalledMethod() 
{
    std::vector<Action> actions;
    actions.reserve( 10 );
    for (int i = 0; i < 10; i++) 
    {
        actions.push_back( Action(....) );
    }
    // use actions, synchronous
    executor.Execute(actions);
    // now actions can be deleted
}

如果Action是一个基类,而您拥有的实际类型是一个派生类,那么您将需要一个指针或智能指针和new。但是,如果Action是一个具体类型,并且所有元素都是该类型,并且该类型是默认可构造、可复制和可赋值的,则不需要。

一般来说,不使用new而获得性能优势是极不可能的。在c++中,当对象的作用域是局部函数作用域时,使用局部函数作用域是很好的实践。这是因为在c++中,你必须更多地关注资源管理,这是通过一种被称为"RAII"的技术来完成的——这本质上意味着关注资源如何在分配点被删除(通过对象的析构函数)。

高绩效更有可能通过以下方式实现:

  • 正确使用算法
  • 适当的并行处理和同步技术
  • 有效缓存和延迟求值。

尽管我很讨厌高频交易,但我还是要告诉你如何在给定的铁上从每个线程中获得最大的性能。

下面是一个示例的解释,其中最初编写的程序速度提高了730倍。

你要分阶段做。在每个阶段,你都要找到一些需要花费大量时间的问题,然后对其进行修复。关键字是find,而不是guess。太多的人只是盯着代码看,然后修复他们认为有帮助的地方,通常但并不总是有帮助。这是猜测。要获得真正的加速,您需要找到所有问题,而不仅仅是您能猜到的少数问题。

如果您的程序正在执行new,那么在某些时候可能需要修复。但这不是唯一的。

理论背后的

对于优秀的高频交易商店的高性能交易引擎,避免c++代码中的new/malloc是基本的。