2013-04-10 27 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上,這種情況已經很少了。