如何解决如何在不使用极端内存的情况下快速在 gRPC (c#) 中流式传输大型数组?
我想使用 gRPC 来流式传输大型数据数组(多 GB)。为此,我以每个几 MB 的小包发送阵列。我遇到的问题是服务器端和客户端都分配了大量缓冲区,而 GC 在清理这些缓冲区时非常懒惰。这意味着当发送 2 GB 数组时,客户端和服务器端都可以将整个数组保存在内存中,就像临时非 GCed 缓冲区一样。
在服务器端,流媒体服务看起来像下面的代码。问题似乎是消息(DataArrayPart - 使用 protobuffers 自动生成)包含一个字段 Data,它是一个重复的浮点数字段。写入此字段时,除了使用 Clear 和 Add 方法外,无法直接复制到 Data 内部的数组中。这意味着必须为每条消息清除并重新分配整个缓冲区,而 GC 几乎急于清理这些缓冲区。
我当然可以逐个元素编写,如下面的注释部分所示。但这会减慢速度,大约 30%。当然也有一些可能的 hack,例如使用反射访问 Data 中的底层数组(它是私有成员)或强制 GC 运行。但一定有更好的方法,或者?
public override async Task StreamRead(StreamRequest request,IServerStreamWriter<global::DataArrayPart> responseStream,ServerCallContext context)
{
// Note that the variable data contains the data to be sent.
int max_size = 1000_000;
int n = data.Length;
float[] arr = new float[max_size];
var da = new DataArrayPart();
da.TotalSize = n;
for (int i = 0; i < n - max_size; i += max_size)
{
System.Buffer.BlockCopy(data,4 * i,arr,4 * max_size);
// Copy into the buffer fast
da.Data.Clear();
da.Data.Add(arr);
// Slow copy - but prevents extensive memory use.
//for (int k = 0; k < arr.Length; k++)
// da.Data[k] = arr[k];
await responseStream.WriteAsync(da);
}
// Send the last n - max_size elements. Not implemented.
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。