【发布时间】:2023-02-20 00:01:06
【问题描述】:
我的 C# 代码中有一个大对象,它可以大到 15GB。在内部,它有一个双精度二维数组和 2 个描述二维数组的行和列的字符串列表。
这个对象有一个方法WriteToTextWriter(StreamWriters),它将二维数组中的一个头和整个数据写入StreamWriters。 StreamWriter 是使用 MemoryStream 对象初始化的。
我有另一个类使用 HttpClient 将数据从 Stream 发布到远程服务器。
它有一个方法PostStreamData(string URL, Stream s)。
我当前的代码是这样的:
var x = MyLargeObject();
using (var memStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memStream))
{
x.WriteToTextWriter(streamWriter);
customClient.PostStreamData(url, memStream);
}
在内部,PostStreamData使用传入的流对象创建一个StreamContent(),将此内容设置为HttpRequestMessage对象的Content属性,最后使用SenAsync方法发送。
由于这使用了MemoryStream,因此当对象大小大于 2GB 时它会失败。看到这个:Failed to write large amount of data to stream
为了克服这个问题,我使用了在那里实现的 HugeMemoryStream 类。但现在的问题是我使用了两倍的内存。 15GB 用于 MyLargeObjet 已经在内存中,然后另外 15GB 用于使用它创建的 HugeMemoryStream 对象。
我认为更好的解决方案是实现一个基于 Stream 的类,它使用大小有限的缓冲区但仍然允许大于 2GB 的对象。如何实施?我正在寻找一些示例代码。它不一定是完整的,但现在我什至不知道如何开始。
【问题讨论】:
-
如果你想减少内存使用,不要使用内存流。无论如何,您可能希望在许多较小的请求中通过 http 发送数据。
-
我看到几个小错别字:
SenAcync和MyLargeObjet -
那时我遇到了类似的问题。目标设备是一个小型 arm64 设备,具有较小的 ram,但它有足够的存储空间。因此,每当我们必须向该设备发送更新时,我们必须将字节数组拆分为多个包。我们发送给设备的第一条消息是;它应该期望多少包和千字节。收到每个包裹后,它会检查包裹是否都在。如果是;我们连接了收到的包裹。这是处理它的一种方法。
-
您是否检查过为什么要分配额外的内存,我的盲目猜测是您正在内存流中分配字符串。 int 和 float 的字符串表示将比二进制表示占用更多空间。如果首先加载二进制对象并创建字符串,您将在内存中拥有原始副本和膨胀副本
-
为什么不能直接写入 HttpClient 中的响应流?那应该消除对额外内存流的需要
标签: c# .net algorithm http memory