1

任何有兴趣了解我来自哪里的人都可以参考第 1 部分,但这不是必需的。

写入文件需要针对大流量进行优化

下面是我编写的一段代码,用于从代理 API 捕获一些金融报价数据。代码将毫无错误地运行。我需要优化代码,因为在高峰时段 zf_TickEvent 方法每秒会调用超过 10000 次。我使用内存流来保存数据,直到达到一定大小,然后将其输出到文本文件中。

代理 API 只是单线程的。

void zf_TickEvent(object sender, ZenFire.TickEventArgs e)
{

    outputString = string.Format("{0},{1},{2},{3},{4}\r\n",
                        e.TimeStamp.ToString(timeFmt),
                        e.Product.ToString(),
                        Enum.GetName(typeof(ZenFire.TickType), e.Type),
                        e.Price,
                        e.Volume);

    fillBuffer(outputString);

}

public class memoryStreamClass
{
    public static MemoryStream ms = new MemoryStream();
}

void fillBuffer(string outputString)
{

    byte[] outputByte = Encoding.ASCII.GetBytes(outputString);

    memoryStreamClass.ms.Write(outputByte, 0, outputByte.Length);

    if (memoryStreamClass.ms.Length > 8192)
    {
        emptyBuffer(memoryStreamClass.ms);
        memoryStreamClass.ms.SetLength(0);
        memoryStreamClass.ms.Position = 0;
    }
}

void emptyBuffer(MemoryStream ms)
{
    FileStream outStream = new FileStream("c:\\test.txt", FileMode.Append);

    ms.WriteTo(outStream);
    outStream.Flush();
    outStream.Close();
}

问题:

  1. 有什么建议可以让这更快吗?我将尝试改变缓冲区长度,但就代码结构而言,这(几乎)是最快的吗?

  2. 当内存流被填满并且我将它清空到文件中时,新数据会发生什么?在清空第一个缓冲区时,是否需要实现第二个缓冲区来保存该数据?还是 c# 足够聪明才能弄清楚?

感谢您的任何建议

4

2 回答 2

2

最快的方法是让一个(或多个)线程将byte[]'s 放入 aBlockingCollection中,并让一个线程尽可能快地取出项目并将它们写入文件。这样你的生产者和文件写入消费者就完全解耦了。这样做,您将能够承受非常高的负载。

于 2012-06-04T15:47:18.643 回答
0

至于第二个问题:由于您的程序是单线程程序,因此在刷新流时将忽略传入的数据,因为执行流将在刷新时停止。但我想你使用的框架是异步工作的。在这里你可能无法避免多线程。您必须同步对流的访问。正如@usr 所说,最好的方法是实现生产者-消费者模式。
多线程是一个高级主题,但它是现代编程中必须了解的。考虑学习它,不要忽视。

于 2012-06-09T04:37:32.040 回答