繁体   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