标签: micro-optimization

JQuery:我的'滚动'事件很慢.我究竟做错了什么?

我有4 DIV,scroll当你滚动其中一个div时我想要一个事件被触发.这是下面的代码.

$('#div1, #div2, #div3, #div4').scroll(function() {
    alert('...');
});
Run Code Online (Sandbox Code Playgroud)

在Firefox/Chrome中,运行速度很快; 但是,在Internet Explorer中,它运行速度很慢,实际上阻止了我滚动div.

我正在使用最新版本的JQuery(v.1.4.1).

问题:运行上面的代码有更有效的方法吗?如果是这样,怎么样?

更新:自从被问及,我已经在我的整个代码下面包含:

$('#div1, #div2, #div3, #div4').scroll(function() {
   /* find the closest (hlisting) home listing to the middle of the scrollwindow */ 
    var scrollElemPos = activeHomeDiv.offset();
    var newHighlightDiv = $(document.elementFromPoint(
        scrollElemPos.left + activeHomeDiv.width()  / 2,
        scrollElemPos.top  + activeHomeDiv.height() / 2)
    ).closest('.hlisting');
    if(newHighlightDiv.is(".HighlightRow")) return;
    $('.HighlightRow').removeClass("HighlightRow");
    newHighlightDiv.addClass('HighlightRow');

   /* change the map marker icon to denote the currently focused on home */
   var activeHomeID = newHighlightDiv.attr("id"); …
Run Code Online (Sandbox Code Playgroud)

javascript jquery micro-optimization

3
推荐指数
1
解决办法
7520
查看次数

重复文字和硬编码

我发现以下模式经常发生:

 b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
Run Code Online (Sandbox Code Playgroud)

请注意,文字字符串使用了两次.提取物来自nginx源库.

在编译单元中遇到这些文字时,编译器应该能够合并这些文字.

我的问题是:

  1. 当在编译单元中遇到时,商业级编译器(VC++,GCC,LLVM/Clang)是否会删除此冗余?
  2. 链接目标文件时,(静态)链接器是否会删除此类冗余.
  3. 如果2适用,这种优化会在动态链接期间发生吗?
  4. 如果1和2适用,它们是否适用于所有文字.

这些问题很重要,因为它允许程序员在不损失效率的情况下进行冗长 - 即,考虑将大量静态数据模型硬连接到程序中(例如,某些低级方案中使用的决策支持系统的规则) .

编辑

2分/澄清

  1. 上面的代码由公认的"主"程序员编写.这家伙一手写了nginx.

  2. 我没有问过文字硬编码的哪种可能机制更好.所以不要偏离主题.

编辑2

我最初的例子是非常人为的和限制性的.以下代码段显示了嵌入到内部硬编码知识中的字符串文字的用法.第一个片段用于配置解析器告诉它为哪个字符串设置哪个枚举值,第二个片段通常用作程序中的字符串.我个人对此感到满意,只要编译器使用字符串文字的一个副本,并且由于元素是静态的,它们不会进入全局符号表.

static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
   { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
   { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
   { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
   { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
   { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
   { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
   { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
   { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
   { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
   { ngx_null_string, 0 }
};
Run Code Online (Sandbox Code Playgroud)

紧随其后:

static ngx_str_t  ngx_http_gzip_no_cache = ngx_string("no-cache");
static ngx_str_t  ngx_http_gzip_no_store …
Run Code Online (Sandbox Code Playgroud)

c c++ compiler-theory micro-optimization string-interning

3
推荐指数
3
解决办法
1451
查看次数

孩子和后代选择者之间的表现有差异吗?

我可以使用子组合器编写CSS选择器,>或者只是指示任何后代的空格.例如,我有这个HTML代码:

<span id='test'>
    <a href="#">Hello</a>
</span>
Run Code Online (Sandbox Code Playgroud)

我可以用以下两种方式编写CSS代码:

#test > a {
    ...
}
Run Code Online (Sandbox Code Playgroud)

要么

#test a {
    ...
}
Run Code Online (Sandbox Code Playgroud)

编写以下CSS代码的最佳方法是什么?

css performance css-selectors micro-optimization

3
推荐指数
1
解决办法
817
查看次数

条件分支的落后方更有效吗?把它作为错误处理方面是一个好主意吗?

考虑一个调用另一个函数并检查错误的函数.假设函数CheckError()在失败时返回0,其他数字表示成功.

第一个版本:取得成功分支或落入错误处理代码(位于函数中间).

    CALL   CheckError
    TEST   EAX,EAX    ;check if return value is 0
    JNZ    Normal
ErrorProcessing:
    ...    ;some error processing code here
Normal:
    ...    ;some usual code here
Run Code Online (Sandbox Code Playgroud)

第二个版本在错误时采取分支,或者通过正常路径.错误处理代码位于函数的末尾.

    CALL   CheckError
    TEST   EAX,EAX
    JZ     ErrorProcessing
Normal:
    ...    ;some usual code here
ErrorProcessing:
    ...    ;some error processing code here
Run Code Online (Sandbox Code Playgroud)

这两种方法中哪一个更好?为什么?

就个人而言,我认为第一个代码具有更好的代码结构(更易读和可编程),因为代码是紧凑的.但是,我也认为第二个代码通常具有更好的速度(在无错误的情况下),因为一个未采用的条件跳转需要2-3个时钟周期(可能我在这里太挑剔)少于一个.

无论如何,我发现我测试的所有编译器在编译if语句时都使用第一个模型.例如:

if (GetActiveWindow() == NULL)
{
    printf("Error: can't get window's handle.\n");
    return -1;
}
printf("Succeed.\n");
return 0;
Run Code Online (Sandbox Code Playgroud)

这应编译为(没有任何exe入口例程):

    CALL [GetActiveWindow]    ;if (GetActiveWindow() == NULL)
    TEST …
Run Code Online (Sandbox Code Playgroud)

optimization x86 assembly micro-optimization

3
推荐指数
1
解决办法
425
查看次数

英特尔内在函数中的延迟与吞吐量

我认为我对延迟和吞吐量之间的差异有一个很好的理解.但是,对于Intel Intrinsics来说,延迟对指令吞吐量的影响并不清楚,特别是在顺序(或几乎顺序)使用多个内部调用时.

例如,让我们考虑一下:

_mm_cmpestrc
Run Code Online (Sandbox Code Playgroud)

它的延迟为11,Haswell处理器的吞吐量为7.如果我在一个循环中运行这个指令,那么在11个循环后我会得到一个连续的每循环输出吗?由于这需要一次运行11条指令,并且因为我的吞吐量为7,所以我是否会用完"执行单元"?

我不确定如何使用延迟和吞吐量,除了得到一条指令相对于不同版本的代码需要多长时间的印象.

performance x86 sse intrinsics micro-optimization

3
推荐指数
1
解决办法
1419
查看次数

有比地图更好的选择吗?

好吧,我正在制作一个c ++程序,它经历了很长的符号流,我需要存储信息以便进一步分析,在流中出现一定长度的符号序列.例如,在二进制流中

100110010101

我有一个长度为6的序列,如下所示:

  • 100110从位置0开始
  • 001100从位置1开始
  • 011001从位置2开始
  • 等等

我需要存储的是所有位置的向量,在那里我可以找到一个特定的序列.所以结果应该像表格一样,可能类似于哈希表,如下所示:

序列/位置

10010101 | 1 13 147 515

01011011 | 67 212 314 571

00101010 | 2 32 148 322 384 419 455

等等

现在,我认为将字符串映射到整数很慢,所以因为我预先在流中有关于符号的信息,所以我可以用它将这个固定长度的序列映射到一个整数.

下一步是创建一个映射,将这些"表示整数"映射到表中的相应索引,在此我添加该序列的下一个出现.然而,这是缓慢的,比我能负担得慢得多.我尝试了std和boost库的有序和无序映射,没有足够的效率.我测试了它,地图是这里真正的瓶颈

这是伪代码中的循环:

for (int i=seqleng-1;i<stream.size();i++) {
    //compute characteristic value for the sequence by adding one symbol
    charval*=symb_count;
    charval+=sdata[j][i]-'0';
    //sampspacesize is number off all possible sequence with this symbol count and this length
    charval%=sampspacesize;
    map<uint64,uint64>::iterator &it=map.find(charval);
    //if index exists, add starting position of the sequence to the table …
Run Code Online (Sandbox Code Playgroud)

c++ optimization micro-optimization

3
推荐指数
1
解决办法
141
查看次数

如果没有副作用,编译器/ JIT可以优化短路评估吗?

我有一个测试:

if(variable==SOME_CONSTANT || variable==OTHER_CONSTANT)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在第二次测试分支比简单操作需要更多周期的平台上,是否允许优化器将其||视为简单|

c# short-circuiting micro-optimization

3
推荐指数
1
解决办法
324
查看次数

在单CPU指令中可以在0和1之间翻转位/整数/布尔值的任何可能代码

单个x86指令可以在"0"和"1"之间切换布尔值吗?

我想到了以下方法,但都导致了两个指令与-cc标志的gcc.

status =! status;

status = 1 - status;

status  = status == 0 ? 1: 0;

int flip[2] = {1, 0};
status = flip[status];
Run Code Online (Sandbox Code Playgroud)

有更快的方法吗?

这就是我尝试过的:https://godbolt.org/g/A3qNUw


我需要的是一个切换输入和返回的函数,以编译为一条指令的方式编写.与此功能类似的东西:

int addOne(int n) { return n+1; }
Run Code Online (Sandbox Code Playgroud)

将Godbolt编译为:

  lea eax, [rdi+1]    # return n+1 in a single instruction
  ret
Run Code Online (Sandbox Code Playgroud)

c c++ x86 assembly micro-optimization

3
推荐指数
1
解决办法
764
查看次数

从GP regs加载xmm

假设你有值rax,rdx你想加载到xmm寄存器中.

一种方法是:

movq     xmm0, rax
pinsrq   xmm0, rdx, 1
Run Code Online (Sandbox Code Playgroud)

虽然这很慢!有没有更好的办法?

x86 assembly sse simd micro-optimization

3
推荐指数
1
解决办法
224
查看次数

当前的 C++ 编译器是否曾经发出过“rep movsb/w/d”?

这个问题让我想知道,当前的现代编译器是否曾经发出REP MOVSB/W/D指令。

基于此讨论,似乎REP MOVSB/W/D在当前 CPU 上使用可能是有益的。

但无论我如何尝试,我都无法让当前的任何编译器(GCC 8、Clang 7、MSVC 2017 和 ICC 18)发出这条指令。

对于这个简单的代码,emit 可能是合理的REP MOVSB

void fn(char *dst, const char *src, int l) {
    for (int i=0; i<l; i++) {
        dst[i] = src[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

但是编译器会发出一个未优化的简单字节复制循环,或者一个巨大的展开循环(基本上是内联的memmove)。是否有任何编译器使用此指令?

c++ x86 assembly micro-optimization compiler-optimization

3
推荐指数
1
解决办法
709
查看次数