簡體   English   中英

C#高速數據記錄數據處理

[英]C# high speed data logging data handling

我編寫了一個應用程序,通過UDP記錄來自嵌入式系統的跟蹤數據。 目前,我收到數據報並解析出可變長度記錄並將它們存儲在列表中。 前端可以訪問列表並顯示數據(圖形和文本列表等)。

我遇到的問題是,有時我需要記錄大量的數據。 我的列表實現導致了內存不足異常。

我的要求是:

  • 允許多線程讀取和寫入數據(不能只是發布過程)
  • 處理大量數據(最壞情況~2MB / s ... 7.2GB /小時的日志記錄)
  • 允許存儲數據集
  • 隨機讀取,基於索引,訪問

有沒有人對如何攻擊這個有一些建議? 以下是我的一些想法:

  • 我想要一個漂亮的磁盤支持,內存緩存List。 這似乎是存在的東西,但我還沒找到。
  • 本地數據庫? 我不太了解數據庫,但它似乎有點過分。
  • 立即將數據存儲到文件中。 在內存中保留一個列表,其中包含每個記錄索引的字節偏移量。 我的讀者可以同時訪問嗎?

本地數據庫確實是處理這種情況的好方法 - 特別是因為查詢可以幫助您調查日志。 另外,你的UDP接收程序可能只是一個單獨的線程,它會在數據庫中發送信息(如果你的數據真的快節奏,你可以有兩個緩沖區並在它們之間交替;將完整的緩沖區刷新到數據庫,而另一個是填滿)。 這實際上取決於你的項目規模。

您可以隨時使用第三個選項(立即存儲到文件中),並使用單獨的“日志調查”工具來讀取該文件而不會遇到OOM異常。

.NET 4具有Lock free隊列。 您可以設置一個隊列,其中一個線程將UDP組件中的內容添加到日志中,另一個線程正在使用這些日志並將它們放入文件或數據庫中。

我所擁有的是一個隊列,我添加了我正在使用Log(字符串內容)方法登錄的消息。 我有另一種方法,我在后台線程中開始,它不斷讀取隊列並寫入文件。 即使在太多數據通過之后可以完成寫入,也會保留時間戳。

日志記錄方法是靜態的和公共的,因此可以從任何線程調用它。 我不能保證這個代碼編譯,因為我把它從我的項目中刪除並刪除了一些東西。

我發現由於我的計算機DISK I / O很糟糕,我沒有收到超過1或2個線程寫入的性能提升。 如果將日志記錄拆分為多個文件,則可能會加快速度,但不能肯定地說。

private static StreamWriter sw;
private static Queue<string> logQueue = new Queue<string>();
public static string logLock = "";
public static void LogLoop()
{
    sw = new StreamWriter("logFilePath.log"), true);
    sw.AutoFlush = true;
    while (true)
    {
        while (logQueue.Count > 0)
        {
            string s = "";
            lock (logLock) // get a lock on the queue
            {
                s = logQueue.Dequeue();
            }
            sw.WriteLine(s);                
        }
        Thread.Sleep(10);
    }
}
public static void Log(string contents)
{
    contents = DateTime.Now.ToString("MM-dd-yy - HH:mm:ss ffff") + " - " + contents; // add a timestamp

    lock (logLock) // get a lock on the queue
    {
        logQueue.Enqueue(contents);
    }
}

這就是我開始后台線程方法的方法。

Thread logThread = new Thread(LogLoop);
logThread.IsBackground = true;
logThread.Name = "Logging Thread";
logThread.Start();

我正在使用Josiah的方法來創建一個可重用的Logger類。 但是,我使用一個標志而不是while(true),允許循環在設置為false時終止。

while (logging)  // instead of while(true)
{
    while (logQueue.Count > 0)
    {
        string s = "";
        lock (logLock)
        {
           s = logQueue.Dequeue();
        }
        write(s);
    }
    Thread.Sleep(timer);
}

它運行良好,但我發現在logQueue.Count值實際更改之前可以將數千條消息排入隊列。

for (int i = 0; i <5000; i++)
{
     lock (logLock)
     {
       logQueue.Enqueue(i.toString());
     }
}
logging = false;

有時,上述代碼會導致LogLoop在實際寫入文件之前終止。 在將日志記錄設置為false之前暫停,但是我仍然感到驚訝的是,在隊列識別消息之前,logQueue.Count並不總是會發生變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM