1. 程式人生 > >專案優化小計

專案優化小計

最近對一個老專案進行優化升級

專案簡介:

通過預設的模型,結合部品屬性、歷史銷量,預測未來十二個月的銷量。

現狀:

1、老專案已在使用,資料庫和應用伺服器都採用的很好的伺服器,每次計算5W個品種,30個模型,耗時5小時。

2、因為某些原因,專案推廣時只能使用個人電腦(2核4執行緒,資料庫為遠端連線),而又需要對所有部品進行試算,單機環境下幾天還沒有算完,馬上要到交付客戶時間點了。

經過調研,

1、該專案程式碼結構清晰

2、分層較多且類庫命名容易使人在理解上產生混淆,不利於運維。

3、最重要的一點,單執行緒序列計算,效率低下,個人電腦下單品種需要大概1分鐘。

優化過程:

1、因為試算結果的交付時間特別緊迫,而對專案內部模型處理一知半解,未能很好的查到系統瓶頸,一時不好對專案程式碼進行處理,因此直接簡單的使用Orleans進行封裝,採用多臺電腦分散式計算,先在客戶要求的時間內計算一版結果應對專案推廣。

2、通過上述處理,前期推廣完成,並採集了自定義的一些日誌,結合程式碼分析,得出結論:模型計算非常快,資料讀取較慢,而資料儲存從一開始的很快到特別慢且會發生失敗。另外,程式碼分析結果為執行緒資源完全未利用上、資料庫操作無批量。

     制定優化策略為,利用生產者-消費者模式批量讀取資料、批量消費資料,並將執行緒資源利用上,若仍然不達標,再考慮分散式處理。

3、落地處理

     3.1 將模型引數載入、模型計算和模型儲存三塊分開為三部分,每部分建立多個執行緒並行處理,並利用BlockingQueue和訊號量進行執行緒同步,然後設定生產者資料容量上限引數、生產者每批讀取品種數引數、觸發生產者資料讀取的閾值(在消費執行緒消費到該值時觸發新資料讀取)、各部分執行緒數引數、批量資料儲存量引數。 這期間,既要防止執行緒空轉、控制記憶體佔用,又要儘可能提升各部分的效率。

     3.2 對於資料的批量儲存,對四種方式進行了對比

             使用Begin End塊批處理多行SQL文字(SQL 文字大小和快取區大小難以控制)

             使用ODP Bulk匯入DataTable(只支援單表內部事務操作,失敗時回滾會耗費更長時間)

             使用Command BIndByName進行引數陣列批量操作(對網路要求高,網路不穩定時容易失敗,但是支援整體事務)

             使用async方式非同步操作SQL(如果使用await,那麼和序列在整體時間耗費上區別不大)

       最終,考慮最終環境是內網連線,採用了Command BIndByName進行引數陣列批量操作,並進行了多批次完整品種測算,無異常發生。

      3.3 分散式作為最後一個優化點,考慮採用Orleans或者自建,鑑於實際情況,暫未實現。

  經過優化,全部品種在單機的測算完成時間穩定在30分鐘左右,已然達標。

  這其中的執行環境影響:客戶端請求量特別小、 應用伺服器的CPU及記憶體的要求不高、資料庫IO和網路IO要求高。