我正在编写HFT交易软件。我确实关心每一微秒。现在它是用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
}
我想超低延迟软件不应该过多使用“新”关键字,所以我将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
}
可能我应该尽量避免使用“新”关键字?我可以使用预分配对象的一些“池”:
// 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
请注意,这是超低延迟,因此我们假设性能优于可读性可维护性等。
答案 0 :(得分:4)
在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是一个具体的类型并且所有元素都属于这种类型,并且如果这种类型是默认可构造的,可复制的和可赋值的,则不需要。
一般而言,您的性能优势不太可能来自不使用新功能。这是在C ++中使用本地函数作用域的好习惯,当它是对象的作用域时。这是因为在C ++中你必须更加关注资源管理,这是通过一种称为&#34; RAII&#34; - 这实质上意味着在分配点处理资源将如何被删除(通过对象的析构函数)。
高性能更有可能通过以下方式实现:
答案 1 :(得分:2)
尽管我厌恶HFT,但我会告诉你如何在给定的铁片上获得每个线程的最大性能。
Here's an explanation一个例子,其中最初编写的程序的速度提高了730倍。
你是分阶段完成的。在每个阶段,您都会发现需要花费大量时间的东西,并且您可以修复它。 关键字是 find ,而不是 guess 。 有太多人只关注代码,并修复他们认为有用的东西,而且往往但并非总是有帮助,有些人。 这是猜测。 要获得真正的加速,您需要找到所有问题,而不仅仅是您可以猜到的几个问题。
如果你的程序正在执行 new ,那么很有可能在某些时候你需要修复它。 但这不是唯一的事情。
答案 2 :(得分:0)
对于高级HFT商店的高性能交易引擎,避免使用C ++代码中的new / malloc是基本的。