如何一次将超过25000条记录/行读写到文本文件中?

时间:2019-02-14 15:55:00

标签: c# websocket filestream

我正在使用Web套接字将我的应用程序与股市实时数据提供者连接起来。因此,当市场活跃起来并且插座打开时,一分钟内能给我近45000条线路。一次我要逐行反序列化 然后将该行写入文本文件,然后读取文本文件并删除文本文件的第一行。因此,使用套接字处理另一个进程变得很慢。因此,请您能帮我,我应该如何在一分钟内非常快地执行该过程,例如将近25000行。

{{1}}

如何快速进行处理,如果应用程序执行此操作,则需要将近3000到4000个符号。如果没有任何进程,则每分钟执行25000行。那么,如何使用所有这些代码来增加行执行时间/过程呢?

1 个答案:

答案 0 :(得分:3)

首先,您需要清理代码以获取更多可见性,我进行了快速重构,这就是我所得到的

const string FilePath = @"D:\Aggregate_Minute_AAPL.txt";

class SomeClass
{
    public string Sym { get; set; }
    public string Other { get; set; }
}

private void Something() {
    File
        .ReadLines(FilePath)
        .AsParallel()
        .Select(x => x.TrimStart('[').TrimEnd(']'))
        .Select(JsonConvert.DeserializeObject<List<SomeClass>>)
        .ForAll(WriteRecord);
}

private const string DirPath = @"D:\COMB1\MinuteAggregates";
private const string Separator = @",";

private void WriteRecord(List<SomeClass> data)
{
    foreach (var item in data)
    {
        var fileNames = Directory
            .GetFiles(DirPath, item.Sym+"_*.txt", SearchOption.AllDirectories);
        foreach (var fileName in fileNames)
        {
            var fileLines = File.ReadAllLines(fileName)
                .Skip(1).ToList();
            var lastLine = fileLines.Last();
            if (!lastLine.Contains(item.Sym))
            {
                fileLines.RemoveAt(fileLines.Count - 1);
            }
            fileLines.Add(
                new StringBuilder()
                    .Append(item.Sym)
                    .Append(Separator)
                    .Append(item.Other)
                    .Append(Environment.NewLine)
                    .ToString()
            );
            File.WriteAllLines(fileName, fileLines);
        }
    }
}

使用List.AsParallel可以更容易地从此处开始操作,以检查代码的方式和参数更快。

也:

  • 您两次打开写入文件
  • 删除操作也有些昂贵,索引0更大(但是,如果元素较少,则不会有太大区别
  • if(fileNames.Length > 0)是没有用的,请使用for,如果列表为空,则for将会跳过
  • 您可以尝试使用StringBuilder代替字符串插值

我希望这些提示可以帮助您改善时间!而且我还没有忘记什么。

编辑


  

我们的目录中有将近10,000个文件。所以当过程是   运行时,它传递了一个错误,表明该进程无法访问   文件,因为它正在被另一个进程使用

那么,您的过程行中是否存在重复的文件名?

如果是这种情况,您可以尝试一种简单的方法,几毫秒后重试,类似

private const int SleepMillis = 5;
private const int MaxRetries = 3;

public void WriteFile(string fileName, string[] fileLines, int retries = 0)
{
    try
    {
        File.WriteAllLines(fileName, fileLines);
    }
    catch(Exception e) //Catch the special type if you can
    {
        if (retries >= MaxRetries)
        {
            Console.WriteLine("Too many tries with no success");
            throw; // rethrow exception
        }
        Thread.Sleep(SleepMillis);
        WriteFile(fileName, fileLines, ++retries); // try again
    }
}

我试图保持简单,但有一些注释: -如果您可以使方法async,可以通过更改Task.Delay的睡眠来改善,但是您需要了解并了解异步的工作原理 -如果碰撞频繁发生,则应尝试另一种方法,例如使用semaphores

的并发映射

第二次修改


  

在实际情况下,我正在连接到websocket并收到70,000   每分钟有1个lac记录,之后我将这些记录分为两部分   记录实时流数据并存储在自己的文件中。和   当我将我们的概念应用于11,000个文件时,速度变慢了

这是一个难题,据我了解,您正在谈论的是每秒1166条记录,在这种规模下,小细节可能会成为大瓶颈。

在那个阶段,我认为最好考虑其他解决方案,它可能是磁盘的I / O太多,网络的线程太多或太少了……

您应该首先对应用程序进行性能分析,以检查该应用程序在哪里花了更多时间专注于该领域,正在使用多少资源?您有多少资源?内存,处理器,垃圾收集器,网络如何?你有SSD吗?

您需要清楚地了解让您放慢脚步的原因,以便您可以直接进行攻击,这将取决于很多因素,这部分的帮助很困难:(。

tons of tools for profile c# apps,有很多方法可以解决此问题(将费用分散在多个服务器上,使用redis之类的东西来快速保存数据,还有一些事件存储以便可以使用事件。...