[英]Limit CPU usage of a process
我有一個服務運行,它定期檢查文件夾中的文件,然后處理它。 (讀取它,提取數據,將其存儲在sql中)
所以我在測試盒上運行它,預計需要更長的時間。 該文件有160萬行,它在6小時后仍在運行(然后我回家了)。
問題是它運行的盒子現在已經完全癱瘓了 - 遠程桌面超時了所以我甚至無法停止它來停止這個過程,或者附加一個調試器來看看有多遠等等。它堅固地使用90%+ CPU,以及所有其他正在運行的服務或應用程序
代碼是(從內存中,可能無法編譯):
List<ItemDTO> items = new List<ItemDTO>();
using (StreamReader sr = fileInfo.OpenText())
{
while (!sr.EndOfFile)
{
string line = sr.ReadLine()
try {
string s = line.Substring(0,8);
double y = Double.Parse(line.Substring(8,7));
//If the item isnt already in the collection, add it.
if (items.Find(delegate(ItemDTO i) { return (i.Item == s); }) == null)
items.Add(new ItemDTO(s,y));
}
catch { /*Crash*/ }
}
return items;
}
- 所以我正在努力改進代碼(任何提示贊賞)。
但它仍然可能是一個緩慢的事情,這是好的,我沒有問題,它花了很長時間,只要它不殺死我的服務器。
所以我想要你的好人是:1)我的代碼是否可靠地未經優化? 2)我可以限制代碼塊可能使用的CPU數量嗎?
干杯全都
您可能最好將其設置為空閑優先級,而不是限制其CPU使用率,因此只有在沒有任何其他方法可以執行時才會運行。 其他人已經提到了優化的可能性,所以我不會嘗試進入那個部分。
在列表上執行查找是O(n)操作,這意味着當列表變長時,搜索項目需要更長的時間。 您可以考慮將項目放入.NET 4.0 / 3.5中的HashSet中,或者對早期版本的.NET使用Dictionary ,它可以像索引一樣,如果您需要列表中的項目來維護原始順序,您可以繼續放置它們在列表中,但使用HashSet / Dictionary進行檢查。
您還可以在BackgroundWorker線程中運行此代碼,這將有助於在進程運行時保持UI響應。
在列表中查找是O(n)。 如果文件有160萬行(即160萬個項目),那么你將反復走過一百多萬行的列表,這會浪費很多時間。
正如其他人所建議的那樣,如果你進行了大量的搜索,那么你需要一個更好的數據結構。 一個旨在加快搜索速度的設計。
如果使用.NET 3.5,則可以使用HashSet集合,該集合為搜索提供了分攤的O(1)。 或者字典集合使用的是.NET 2.0
接下來你要問自己,如果文件有160萬行,你有足夠的內存嗎? 如果你這樣做,那么在內存中解析文件比將其發送到數據庫以處理重復文件更快,但如果你沒有足夠的內存,那么你將進行分頁。 很多。 (這可能是現在發生的事情)。
正如其他人所說,修復數據結構。
現在,我的眼睛點擊這句話“定期檢查文件夾中的文件,然后對其進行處理。” 經常“定期”以及為什么處理可能沒有改變的文件?
您可能需要查看System.IO.FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
你不能用SqlBulkCopy類批量加載這個文件,然后在數據庫服務器上進行處理嗎?
你真的需要把所有數據保存在內存中嗎? 您可以將它存儲在數據庫中(如果您需要簡單且功能強大的東西使用Sqlite)並使用sql處理它。
我不是ac#程序員,但看着我認為的邏輯
您每次在循環中創建一個新的字符串對象。 如果我必須在java中執行它,而不是使用字符串對象,我會使用StringBuffer。
您的數據文件很大,所以我認為您應該有邏輯在每'n'個記錄后清除數據庫中的信息。 您需要額外的邏輯來記錄到目前為止已清除的記錄。 或者,由於您的邏輯僅捕獲第一行數據並忽略后續重復項,而不是使用Find方法,您只能嘗試插入數據並捕獲sql失敗。
處理邏輯應該在一個單獨的線程中,以保持系統的響應。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.