假定 STL 列表(作为双链表实现)的“push_back”和“pop_front”方法应该是常量 O(1)。然而,我们在 linux 上运行的应用程序中遇到了 cpu 问题,我们发现“pop_front”方法在使用列表时效率极低。这是列表实现问题还是预期行为?
这是示例代码:
class A {
public:
A() { mA = rand(); mB = rand(); mC = rand(); mD = rand(); }
u32 mA;
u32 mB;
u32 mC;
u32 mD;
};
#define DELTA(t1, t0) ((t1.tv_sec - t0.tv_sec)*1000 + ((t1.tv_usec - t0.tv_usec)/1000))
int main(int argc, char* argv[]) {
std::list<A> l;
std::queue<A> q;
std::deque<A> dq;
printf("Creating nodes...");
std::vector<A> v;
for (int i = 0; i < 100000; ++i) {
A a;
v.push_back(a);
}
printf("OK\n");
timeval t0, t1;
printf("std::deque test: push back...");
gettimeofday(&t0, NULL);
for (std::vector<A>::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
dq.push_back(*iter);
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), dq.size());
printf("std::deque test: pop front...");
gettimeofday(&t0, NULL);
while (dq.size() > 0) {
A a = dq.front();
dq.pop_front();
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), dq.size());
printf("std::queue test: push back...");
gettimeofday(&t0, NULL);
for (std::vector<A>::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
q.push(*iter);
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), q.size());
printf("std::queue test: pop front...");
gettimeofday(&t0, NULL);
while (q.size() > 0) {
A a = q.front();
q.pop();
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), q.size());
printf("std::list test: push back...");
gettimeofday(&t0, NULL);
for (std::vector<A>::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
l.push_back(*iter);
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), l.size());
printf("std::list test: pop front...");
gettimeofday(&t0, NULL);
while (l.size() > 0) {
A a = l.front();
l.pop_front();
}
gettimeofday(&t1, NULL);
printf("Done in %d ms, size = %d\n", DELTA(t1, t0), l.size());
return 0;
}
对于不同数量的节点,我们得到:
5000 个节点:
std::deque test: push back...Done in 0 ms, size = 5000
std::deque test: pop front...Done in 0 ms, size = 0
std::queue test: push back...Done in 0 ms, size = 5000
std::queue test: pop front...Done in 0 ms, size = 0
std::list test: push back...Done in 0 ms, size = 5000
std::list test: pop front...Done in 202 ms, size = 0
10000 个节点:
std::deque test: push back...Done in 0 ms, size = 10000
std::deque test: pop front...Done in 0 ms, size = 0
std::queue test: push back...Done in 0 ms, size = 10000
std::queue test: pop front...Done in 0 ms, size = 0
std::list test: push back...Done in 1 ms, size = 10000
std::list test: pop front...Done in 279 ms, size = 0
100000 个节点:
std::deque test: push back...Done in 5 ms, size = 100000
std::deque test: pop front...Done in 4 ms, size = 0
std::queue test: push back...Done in 3 ms, size = 100000
std::queue test: pop front...Done in 4 ms, size = 0
std::list test: push back...Done in 12 ms, size = 100000
std::list test: pop front...Done in 31148 ms, size = 0
谢谢!
维森特
最佳答案
如果你想检查一个容器是否为非空,你应该使用!c.empty(),而不是c.size() > 0。
这对 std::list 尤其重要,因为在某些实现中,size 是一个线性时间 操作,而不是 恒定时间操作。
(虽然,正如 vsoftco 在评论中指出的那样,C++11 加强了对 size 的要求,它确实是常量——如果你有一个兼容的编译器/库,你可以尝试启用选项为该标准或更高版本编译)
关于c++ - STL 列表性能很差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40110020/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0
我正在寻找一个用ruby演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent
如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=