在使用 Rust 开发Brainfuck解释器时,我注意到cargo bench
当基准包含大型类型时,构建 Criterion 工作台需要花费非常长的时间。
作为 Brainfuck 实现的一部分,我定义了一个具有非常大数组的结构来充当解释器内存。当我使用 进行编译时cargo build --release
,我的 crate 在几秒钟内即可构建完成,但是当我运行时,cargo bench
构建需要 6 分钟以上!我最终意识到这与我的类型定义中的非常大的数组有关([u8; 30_000]
)。我认为我可以通过间接方式使类型更小,因此我将类型更改为 a ,Box<[u8; 30_000]>
这确实显着减少了基准测试的构建时间。
我的问题是:为什么cargo bench
构建比cargo build --release
没有花费更长的时间Box<>
,它们不应该使用相同的优化级别吗?为什么不用cargo build --release
那么长时间Box<>
?
这可能是 Criterion 的一个错误吗?
我确认cargo bench --no-run --timings
几乎所有的时间都在建造长凳本身。我还做了一个最小的可重现示例:
cargo --version
> cargo 1.64.0 (387270bc7 2022-09-16)
Run Code Online (Sandbox Code Playgroud)
cargo --version
> cargo 1.64.0 (387270bc7 2022-09-16)
Run Code Online (Sandbox Code Playgroud)
[package]
name = "large-type"
version = …
Run Code Online (Sandbox Code Playgroud) 我有一个场景,我正在从数据库中读取一些数据。该数据以 的形式返回IAsyncEnumerable<MyData>
。读取数据后我想将其发送给消费者。该消费者是异步的。现在我的代码看起来像这样:
// C#
IAsyncEnumerable<MyData> enumerable = this.dataSource.Read(query);
await foreach (var data in enumerable)
{
await this.consumer.Write(data);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,当我枚举数据库时,我持有数据的锁。我不想持有这把锁的时间超过我需要的时间。
如果消费者消耗数据的速度比生产者生成数据的速度慢,有什么方法可以让我急切地从数据源中读取数据,而无需仅调用ToList
or ToListAsync
。我想避免一次将所有数据读入内存,如果现在生产者比消费者慢,这会导致相反的问题。如果数据库上的锁不是越短越好,我想要在内存中一次有多少数据与我们保持枚举运行多长时间之间进行可配置的权衡。
我的想法是,有某种方法可以使用队列或类似通道的数据结构来充当生产者和消费者之间的缓冲区。
在 Golang 中我会做这样的事情:
// go
queue := make(chan MyData, BUFFER_SIZE)
go dataSource.Read(query, queue)
// Read sends data on the channel, closes it when done
for data := range queue {
consumer.Write(data)
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在 C# 中获得类似的行为?