2

我必须为巨大的有效负载计算哈希,所以我使用流而不是将所有请求内容加载到内存中。问题是这段代码有什么区别:

using (var md5 = MD5.Create())
using (var stream = await authenticatableRequest.request.Content.ReadAsStreamAsync())
{
    return md5.ComputeHash(stream);
}

还有那个:

using (var md5 = MD5.Create())  
using (var stream = new MemoryStream())
{
    await authenticatableRequest.request.Content.CopyToAsync(stream);
    stream.Position = 0;

    return md5.ComputeHash(stream);
}

我在内部期望相同的行为,但也许我遗漏了一些东西。

4

3 回答 3

4

第一个版本看起来不错,让哈希处理流读取。它就是为此而设计的。

ComputeHash(stream)将在 while 循环中读取块并重复调用 TransformBlock()。

但是第二段代码会将所有内容加载到内存中,所以不要这样做:

using (var stream = new MemoryStream())
{
    await authenticatableRequest.request.Content.CopyToAsync(stream);
于 2018-07-31T07:46:01.827 回答
2

第二个代码片段不仅将所有内容加载到内存中,它还将使用HttpContent.ReadAsByteArrayAsync().

MemoryStream 是初始大小为零的byte[]缓冲区上的 Stream API。当数据写入其中时,缓冲区必须重新分配到两倍于原始缓冲区的缓冲区中。这会创建很多大小超过最终内容的临时缓冲区对象。

这可以通过向构造函数提供capacity参数从一开始就分配最大预期缓冲区大小来避免。MemoryStream()

充其量,这将类似于调用:

var bytes = authenticatableRequest.request.Content.ReadAsByteArrayAsync();
return md5.ComputeHash(bytes);
于 2018-07-31T08:05:07.983 回答
2

我期望在内部有同样的行为,

为什么?我的意思是,在一种情况下,您必须将所有内容加载到内存中(因为猜猜看,您定义了一个内存流)。在其他情况下不一定。

于 2018-07-31T07:44:44.703 回答