【发布时间】:2022-01-06 22:12:30
【问题描述】:
在 actix-web 中,可以通过在处理程序中返回来提供文件:
HttpResponse::Ok().streaming(file)
但在这里,file 必须实现 Stream<Item = Result<Bytes, E>> 特征。 crate async_std 中的 File 类型没有实现它,所以我创建了一个实现它的包装器:
struct FileStreamer {
file: File,
}
impl Stream for FileStreamer {
type Item = Result<Bytes, std::io::Error>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut buf = [0; 1024];
self.file.read(&mut buf).poll_unpin(cx).map(|r| {
r.map(|n| {
if n == 0 {
None
} else {
Some(Bytes::copy_from_slice(&buf[0..n]))
}
})
.transpose()
})
}
}
它可以工作,但有一个问题。对于每次调用 read,我们都会创建一个 Bytes 的新实例,这是一个动态分配的缓冲区。
这是在 actix-web 中提供文件的最有效方式吗?
我也觉得,在这种情况下选择合适的缓冲区大小实际上更为关键,因为一个小的缓冲区会导致重复的系统调用,而一个太大的缓冲区会导致内存分配缓慢,甚至不会被完全使用。
我是否可以将重复动态分配视为性能问题?
PS:该文件不是静态的,它会被修改和删除,因此,控制读取过程是必要的。
【问题讨论】:
-
文件是否在文件系统上?
-
肯定的。在本地存储上。
-
您可以根据需要使用文件系统。无需将事情过度复杂化。
标签: performance rust allocation actix-web rust-actix