0

我目前正在通过以下方式从套接字中提取数据

            boost::asio::read_until( *socket, buffer, "\n", error ); 
            std::string s( (std::istreambuf_iterator<char>(&buffer)), std::istreambuf_iterator<char>());

看来拉机制很慢,我需要更快地拉更多数据。关于我可以做些什么来提高性能的任何建议?有没有办法让我创建另一个套接字并将一些提取工作委托给那个套接字?

4

1 回答 1

2

我过去曾在交易应用程序上工作过,我可以告诉您,我从未见过任何订单路由系统或实时报价系统实施过搜索“\n”的协议。FIX 当然不支持这个。这意味着在您的订单路由或实时报价系统的某个地方,有一个应用程序很可能会获取那些可能使用 FIX 协议的报价消息并将它们转换为您现在使用的协议。这很可能至少与系统速度慢的原因有关。

如果每个字符串代表一个股票报价,那么我会考虑重写广播价格更新的系统以批量发送它们,并且每秒发送它们不超过 3 - 5 次 - 假设该系统不被自动化使用交易程序(这将是一个完全不同的主题,需要一种截然不同的方法)。看起来该应用程序也在以 ascii 文本格式发送引号。我会将其更改为使用二进制格式。FIX 已经支持二进制格式很长一段时间了,称为FAST FIX。自定义二进制协议也是可以接受的。

根据您对股票报价进行的处理类型,我会考虑不将每个报价传递给不同的线程。如果唯一的处理仅涉及使用新报价更新窗口,则尤其如此。我将传递整个缓冲区(假设它有超过 1 个引号并且只包含引号)以供用户界面线程处理。如果需要进行其他处理,例如将其保存到磁盘或数据库,那么我将有一个单独的线程来处理这种处理。

您没有向我们展示太多代码。如果客户端应用程序很慢,那么您可以尝试以下一些想法进行改进:

  1. 不要动态创建线程。在应用程序开始时创建一个线程池,并根据需要使用它们。了解太多线程可能比只有一个线程更糟糕,因此在决定线程数时尝试尝试找到一个快乐的平衡点。

  2. 与上述相同,尝试只创建一次对象并在需要时重用它们。这可以通过将一组对象存储在向量、堆栈或队列中来完成。仅当容纳它们的容器已用尽时才创建新对象。如果您的应用程序经常使用 new 运算符在堆上创建对象,则尤其如此。

  3. 在上面的代码中,正如 Panasyuk 指出的那样,缓冲区可以移到 while 循环之外。错误对象也可以。在代码中寻找可以只创建一次对象而不是一遍又一遍地创建对象的其他区域。

  4. 了解何时需要对象的实例 .vs。一个静态的。如果多个线程需要写入对象,通常需要一个对象的实例。当只有一个线程,或者有多个线程只需要从中读取时,可以使用静态对象。

  5. 从处理套接字处理的线程向用户界面线程传递消息时,请确保使用 BeginInvoke 而不是 Invoke。Invoke 是同步的,将等待被调用的方法完成,然后再继续处理。BeginInvoke 是异步的,会立即返回,因此效率更高。如果应用程序正在丢弃消息并且正在使用 Invoke,那么这就是原因。

  6. 由于应用程序正在使用多个线程,因此可以合理地假设存在一些用于防止多个线程同时执行的锁定对象或语句。查看这些情况并确保锁本质上是细粒度的——这意味着为了方便起见,锁没有设置在函数的顶部。将其设置在仅需要它的函数中间的某个位置。确保代码也使用临界区而不是互斥锁,因为 Microsoft 领域的临界区效率更高。唯一需要使用互斥锁的情况是在将 DLL 附加到两个或多个 exe 时,现在很少这样做了。

于 2013-04-10T16:57:40.487 回答