2013-04-10 41 views
0

我目前通过以下方式从插座中提取数据?

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

从插座中提取数据似乎牵引机构是缓慢的,我需要拉更多的数据速度更快。关于我能做些什么来改善表现的建议?有没有办法为我创建另一个套接字并将一些抽取工作委托给那个?

+1

首先,尝试从循环中移出'buffer' - 不应该每次重新创建和重新分配 – 2013-04-10 15:27:00

+0

* slow *是一个相对术语,您期待什么样的性能? – 2013-04-10 16:47:24

+0

因此,您已经对代码进行了剖析,而剖析器指出瓶颈是从套接字读取数据?无论如何,可能值得最小化内存分配和深度拷贝的数量。 – 2013-04-10 17:06:46

回答

2

我曾经在交易应用程序,并可以告诉你,我从来没有见过任何订单路由系统或实时报价系统曾执行协议,它搜索“\ n”。 FIX当然不支持这一点。这意味着,在您的订单路由或实时报价系统的某个地方,有一个应用很可能采用那些可能使用FIX协议并将它们转换为您现在使用的协议的价格报价消息。这很可能至少与系统缓慢的原因有关。

如果每个字符串代表一个股票报价,那么我会考虑重新发布广播价格更新的系统,以批量发送它们,而不是发送更多比每秒3-5次 - 假设系统是没有被自动化交易程序使用(这将是一个完全不同的话题,需要一种截然不同的方法)。它看起来像应用程序也以ASCII文本格式发送报价。我会改变它使用二进制格式。 FIX支持二进制格式相当长一段时间,现在称为FAST FIX。自定义二进制协议也是可以接受的。

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

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

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

  2. 与上面一样,尝试仅创建一次对象并在需要时重用它们。这可以通过将一组对象存储在向量,堆栈或队列中来完成。只有在持有它们的容器已用完时才会创建一个新对象。如果您的应用程序频繁地使用新操作符在堆上创建对象,则尤其如此。

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

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

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

  6. 由于应用程序正在使用多个线程,因此假设有一些锁定对象或语句用于防止多个线程同时执行是合理的。查看这些情况并确保锁定本质上是颗粒状的 - 这意味着为了方便.vs,锁定并未设置在函数的顶部。将它设置在只需要它的函数中间的某个位置。确保代码使用关键部分而不是互斥体,因为Microsoft域中的关键部分效率更高。唯一需要使用互斥体的方式是将DLL附加到两个或更多的exes上,这种情况已经很少了。