带有 FileStreams 的 MimeKit 迭代器
Posted
技术标签:
【中文标题】带有 FileStreams 的 MimeKit 迭代器【英文标题】:MimeKit Iterator with FileStreams 【发布时间】:2020-09-01 05:51:17 【问题描述】:我刚刚设法重写了一些现在应该能够处理用于打印的大型 MIME 文件的代码。
为此,我们以下列方式使用 MimeKit:
var message = MimeMessage.Load(_fileStream, true);
var iter = new MimeIterator(message);
while (iter.MoveNext())
...
这里有趣的是,在我使用fileStream之前,我们曾经复制了一个HttpListenerRequest对象的inputStream,这是一个无法加载到MimeKit的NetworkStream(non-seekable)。
自从添加了 fileStream,对于一个 2GB 的作业,我在 while 循环中花费了大约 40 秒来迭代请求的每个部分,如果你问我的话,这已经很多了……使用 memoryStream 是 6 秒。
这种行为正常吗?是否有机会使用 MimeKit 获得更好的时间,或者我应该实现自己的解析器?
提前致谢!
【问题讨论】:
【参考方案1】:这里有趣的是,在我使用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()循环,可以加起来)。
希望能帮助你解决这个问题。
【讨论】:
您好,我使用分析器进行了一些额外的调试,以了解究竟发生了什么。我确实设法解决了一些问题,这些问题来自我在循环中运行的代码。修复这些后,我对结果很满意,但在执行 DecodeTo 方法时发现了一些零星的行为...... 相同的 2GB 文件有时会在 30 秒以下解码,有时会在 60 秒以上解码...我无法解决导致此问题如此不稳定的问题。这是一个已知问题还是我做错了什么?每次我使用 DecodeTo 都是将数据解码为文件流并将其保存到磁盘。感谢您迄今为止的帮助。 副手,我不确定是什么原因导致的(就 MimeKit 中的代码而言)。 2GB 是很多数据,可能只是由于内核空间切换。我很想知道您是否能够进一步调试并弄清楚发生了什么。 @jsteadfast 最近几天我一直在调试,我唯一设法找到的是超过 10GB 的高速缓存内存并且会降低性能。我注意到最适合我的是使用 Open 而不是 DecodeTo 并执行类似 Open.CopyTo 的操作。据您所知,使用 Open 是否安全? 我以为我已经对此做出了回应,但显然我没有。是的,使用Open()
代替DecodeTo()
是安全的。不过,我不明白它如何/为什么会有所作为。以上是关于带有 FileStreams 的 MimeKit 迭代器的主要内容,如果未能解决你的问题,请参考以下文章