- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我开始优化 crate 的性能,我换了一个 Vec
对于 VecDeque
.容器按排序顺序维护元素(它应该相当小,所以我还没有费心尝试堆)并且偶尔会从中间拆分成两个单独的容器(我还没有尝试过堆的另一个原因) drain
.
我希望第二个操作要快得多:我可以复制集合的前半部分,然后简单地旋转并减少原始(现在是第二个)集合的长度。但是,当我运行 #[bench]
时测试,以可变次数执行上述操作,(低于百万纳秒/迭代)我观察到性能随着 VecDeque
而下降。 :
测试一个
测试 b
测试 c
测试d
维克
12.6
5.9
5.9
3.8
VecDeque
13.6
8.9
7.3
5.8
一个可重现的示例 ( gist ):
#![feature(test)]
extern crate test;
use std::collections::VecDeque;
fn insert_in_sorted_order_vec<E: Ord + Eq>(t: &mut Vec<E>, k: E) {
match t.binary_search(&k) {
Ok(i) => t[i] = k,
Err(i) => t.insert(i, k),
}
}
fn insert_in_sorted_order_vecdeque<E: Ord + Eq>(t: &mut VecDeque<E>, k: E) {
match t.binary_search(&k) {
Ok(i) => t[i] = k,
Err(i) => t.insert(i, k),
}
}
fn split_vec<T>(mut t: Vec<T>) -> (Vec<T>, Vec<T>) {
let a = t.drain(0..(t.len() / 2)).collect();
(a, t)
}
fn split_vecdeque<T>(mut t: VecDeque<T>) -> (VecDeque<T>, VecDeque<T>) {
let a = t.drain(0..(t.len() / 2)).collect();
(a, t)
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
static ITERS_BEFORE_SPLIT: u32 = 50;
static ITERS_TIME: u32 = 10_000;
#[bench]
fn vec_manip(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::new();
for i in 0..(ITERS_TIME / ITERS_BEFORE_SPLIT) {
for j in 1..(ITERS_BEFORE_SPLIT + 1) {
insert_in_sorted_order_vec(&mut v, i * j / (i + j)); // 'random'-ish illustrative number
}
v = split_vec(v).1;
}
});
}
#[bench]
fn vecdeque_manip(b: &mut Bencher) {
b.iter(|| {
let mut v = VecDeque::new();
for i in 0..(ITERS_TIME / ITERS_BEFORE_SPLIT) {
for j in 1..(ITERS_BEFORE_SPLIT + 1) {
insert_in_sorted_order_vecdeque(&mut v, i * j / (i + j)); // 'random'-ish illustrative number
}
v = split_vecdeque(v).1;
}
});
}
}
Vec
实现花费了 69.2k ns/iter,而
VecDeque
实现花费了 91.8k。
cargo bench
获得的.
cargo bench
选项(优化,据我所知没有调试符号等)split_vecdeque
使用方法
split_off
而不是
drain().collect()
(见下文)。看起来这种方法保证不会重新分配或移动任何东西,而只是移动
head
和
tail
周围的指针;见
documentation和
implementation .然而,它的性能甚至比 98.2k ns/iter 的原始 VecDeque 还要差。对于较大的值(ITERS_BEFORE_SPLIT = 50_000,ITERS_TIME = 5_000_000),尽管性能(21.8m ns/iter)优于
drain
(23.1 ns/iter) 并且比
Vec
差(19.1 纳秒/迭代)。
fn split_vecdeque<T>(mut t: VecDeque<T>) -> (VecDeque<T>, VecDeque<T>) {
let a = t.split_off(t.len() / 2);
(t, a)
}
最佳答案
A VecDeque
就像一个 Vec
但支持有效地从两端推送和弹出。为了做到这一点,它使用了一个连续的缓冲区(就像 Vec
一样),但将其视为两个分区;一个头和一个尾部。
结构布局如下:
pub struct VecDeque<T> {
tail: usize,
head: usize,
buf: RawVec<T>,
}
缓冲区中的项目是这样排序的:
[[tail: 5, 6, 7] ...unused... [head: 1, 2, 3, 4]]
将项目添加到集合的末尾将附加到尾部,使用一些未使用的空间。添加到集合的开头将添加到头部的开头,进入相同的空间。当头尾在中间相遇时,
VecDeque
已满,需要重新分配。
Vec
相比:
pub struct Vec<T> {
buf: RawVec<T>,
len: usize,
}
它像这样使用它的缓冲区:
[1, 2, 4, 5, 6, 7 ...unused...]
最后添加一个项目很快,但在开始添加一个项目需要复制所有现有项目以腾出空间。
VecDeque
这种布局变得更加复杂,这将略微降低其性能。甚至检索它的长度也更复杂:
pub fn len(&self) -> usize {
count(self.tail, self.head, self.cap())
}
整点
VecDeque
是为了使某些操作更快,即推送和弹出集合的开始。
Vec
在这方面非常慢,特别是如果有很多项目,因为它涉及移动所有其他项目以腾出空间。
VecDeque
的结构使这些操作更快,但与
Vec
相比以牺牲其他操作的性能为代价.
VecDeque
的设计,因为它们以调用
insert
为主,这涉及在两种情况下对许多项目进行昂贵的复制。
关于data-structures - 为什么 VecDeque 比 Vec 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68351027/
这是我第一次在结构中使用结构。我在编译我的程序时遇到了这个错误。错误:字段“结果”的类型不完整。 错误是指这行代码。-->结构result_t结果; 有什么帮助吗? :)谢谢。 typedef str
typedef struct mensagem { int sender ; int receiver ; char *text ; } *Item ; typedef str
我正在使用 ExpressionEngine 和 Structure 附加组件的最新版本。 我正在寻找有关生成 4 项导航栏的帮助,其中两项位于不同的结构级别。 我的结构行如下所示: 服务(父) --
我正在处理一个非常大的数据集。本质上,我将处理数百万条记录并将值存储到数据集中。 每次我存储一个值时,我必须首先检查以确保该值不在数据结构中。如果值在数据结构中,我必须更新(或删除/添加)记录以更新计
我正在尝试分别使用视频帧和音频来分析视频,我想出了一个看起来像这样的模型 现在,我将训练数据分成两个生成器 - 一个用于视频,一个用于音频。我必须进一步将生成器分成两半,我认为这是我遇到错误的地方。因
我有一个创建 N 个进程的程序,每个进程创建 M 个线程。 我还有一个结构需要传递给线程函数。 当我像这样创建 M 个线程时: thread_args_t** thread_arg = malloc(
我正在试图弄清楚如何实现一个等待事件发出信号的函数。指针由DLL函数返回,该函数是存储3个项的结构。其中两个是句柄,它们只是指针,最后是一些随机的未使用的指针。我真的不确定这应该如何格式化,因为我两个
根据PLCOpen、IEC-61131标准,是否可以在声明中初始化结构体? 我正在考虑类似于 this C++ question 的事情. 最佳答案 您可以在结构声明时向结构变量添加默认值。您还可以在
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
在纯 C 中工作,将结构嵌套在其他结构或指向结构的指针中更好。使用指针可以更容易地实现良好的对齐,但是访问内部结构需要额外的取消引用。只是具体地说: typedef struct {
我正在使用 Qt Creator 开发应用程序。 我不是一个好的C++程序员,所以可能会有概念上的错误等。 我在复制结构数组并返回结构时遇到问题。 有很多与类似标题相关的解决方案,但无法解决我的问题。
我正在尝试使用带水印的 dropDuplicate 函数对流数据进行重复数据删除。我目前面临的问题是我必须为给定记录设置两个时间戳 一个是事件时间戳 - 从源创建记录的时间戳。 另一个是传输时间戳 -
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 10年前关
我尝试构建一个嵌套循环,用于创建 2 维零矩阵来解决 LCS 问题(动态规划)。这后来用于计算 Rouge-L 分数(输入是张量,而不是字符串),但它总是出错引发 ValueError: The tw
我曾多次使用 HDFS 和 Kafka,我注意到 Kafka 比 HDFS 更可靠。因此,现在使用 Spark-structured-streaming 时,我很惊讶检查点仅适用于 HDFS。使用 K
C11,6.7.2.1 结构和 union 说明符,约束,3(添加了强调): A structure or union shall not contain a member with incomple
在 emacs lisp 中,各种树结构是常见的。 custom.el通过:type提供论据 defcustom定义自定义变量的预期形状的标准方法。但是有没有一种标准的方法来验证一些随机 emacs
我在网上遇到了以下面试问题。 描述一个数据结构,其中 getValue(int index)、setValue(int index, int value) 和 setAllValues(int val
我正在使用 sqldf 对一个巨大的文件进行子集化。以下命令为我提供了一个 100 行和 42 列的 data.frame。 first <- read.csv.sql("first.txt", se
来自这里的 C++ 背景。我需要为我的一门类(class)编写 C 语言,但我从未接触过这一类(class)。这两个声明之间有什么区别?为什么要包含 struct 关键字?有不同的含义吗?它们在 C+
我是一名优秀的程序员,十分优秀!