这里有趣的是,在我使用fileStream之前,我们曾经复制过一个HttpListenerRequest对象的inputStream,这是一个无法加载到MimeKit的NetworkStream(non-seekable)。
我不太清楚你上面的意思。你在做这样的事情吗?
var memory = new MemoryStream ();
httpResponse.Stream.CopyTo (memory);
memory.Position = 0;
var message = MimeMessage.Load(memory, true);
自从添加了 fileStream,对于一个 2GB 的作业,我在 while 循环中花费了大约 40 秒来迭代请求的每个部分,如果你问我,这已经很多了......使用 memoryStream 是 6 秒。
您对MimeMessage.Load() 的使用将true 作为persistent 参数传递。这提高了 解析 性能(因为它不再需要在解析后将 MIME 内容加载到 RAM 中),但会对稍后读取单个 MIME 部分内容的性能产生负面影响,因为它需要寻找 _fileStream根据您的请求,每个 MIME 部分的内容的起始偏移量。
这种行为正常吗?
40 秒确实看起来很多,但在不了解您的代码的更多细节的情况下,我无法提出任何建议。
是否有机会使用 MimeKit 获得更好的时间,或者我应该实现自己的解析器?
好吧,我几乎可以保证,如果您实现自己的解析器,它很可能会比 MimeKit 慢几个数量级(看到在 C# 中编写 MIME 解析器的所有其他尝试实际上都比 MimeKit 慢几个数量级MimeKit) ;-)
您需要在这里做的是在分析器下运行您的代码以查看问题出在哪里。
如果性能问题如您在循环内部所建议的那样,则它不是解析器中的性能问题。这是循环中的性能问题。这并不是说 MimeKit 代码不会导致缓慢。
如果问题出在 MimeKit 中,我会怀疑 BoundStream.Read() 内部的这种逻辑:
// make sure that the source stream is in the expected position
if (BaseStream.Position != StartBoundary + position)
BaseStream.Seek (StartBoundary + position, SeekOrigin.Begin);
在您的情况下,BaseStream 应该是您的_fileStream。自从我查看 FileStream.Position 的代码以来已经有一段时间了,但它可能需要一个系统调用来获取该值(并且系统调用不是免费的)。
但是,40 秒是很多时间 - 比我预期的要多,除非每个 MIME 部分的内容都很庞大(MimePart.Content 的流式内容每个循环读取约 4K 并且如果每个循环有 1 个 lseek()循环,可以加起来)。
希望能帮助你解决这个问题。