轻灵,内省,质朴,有为

Tcl中for和foreach的速度比较

+1 投票

先说简单结论:

  • `foreach`的速度比`for`快约一倍
  • `for`比较慢的原因主要是因为多了条件判断语句和`lindex`语句
  • `while`和`for`的速度相当
速度比较结果:
8.5.2
    1633 microseconds per iteration # foreach
    3170 microseconds per iteration # for
    2494 microseconds per iteration # foreach + expr
    2934 microseconds per iteration # foreach + lindex
    3777 microseconds per iteration # foreach + expr + lindex
    3211 microseconds per iteration # while

再上代码:

代码:for-vs-foreach.tcl
puts [info patch]

lassign $argv COUNT

set chars [split [string repeat x 4096] ""]

proc measure [list name body "N $COUNT"] {
  set time [lindex [uplevel [list time $body]] 0]
  puts [format "%8d microseconds per iteration # %s" $time $name ]
}

measure "foreach" {
  set n 0
  set N 4096
  foreach c $chars {
    set t $c
    incr n
  }
}

measure "for" {
  set n 0
  set N 4096
  for {set n 0 ; set N 4096} {$n<$N} {incr n} {
    set c [lindex $chars $n]
    set t $c
  }
}


measure "foreach + expr" {
  set n 0
  set N 4096
  foreach c $chars {
    expr {$n<$N}
    set t $c
    incr n
  }
}

measure "foreach + lindex" {
  set n 0
  set N 4096
  foreach c $chars {
    set c [lindex $chars $n]
    set t $c
    incr n
  }
}

measure "foreach + expr + lindex" {
  set n 0
  set N 4096
  foreach c $chars {
    expr {$n<$N}
    set c [lindex $chars $n]
    set t $c
    incr n
  }
}

measure "while" {
  set n 0
  set N 4096
  while {$n<$N} {
    set c [lindex $chars $n]
    set t $c
    incr n
  }
}
最新提问 9月 18, 2015 分类:语法命令 | 用户: 风行水上 (-30 分)
修改于 9月 22, 2015 用户:风行水上

3 个回答

0 投票

这俩个差别只是在tcl里面吗?在其他脚本语言是不是也是这样?不过这个判断在其他脚本语言里面都存在,那么应该是一样的。

最新回答 9月 20, 2015 用户: 莫名晴天 (20 分)
0 投票

速度比较结果: Tcl 8.5.17
8.5.17
    1874 microseconds per iteration # foreach
    2952 microseconds per iteration # for
    2570 microseconds per iteration # foreach + expr
    3025 microseconds per iteration # foreach + lindex
    3708 microseconds per iteration # foreach + expr + lindex
    2937 microseconds per iteration # while

速度比较结果: Tcl 8.6.1
8.6.1
    2100 microseconds per iteration # foreach
    2773 microseconds per iteration # for
    2862 microseconds per iteration # foreach + expr
    3162 microseconds per iteration # foreach + lindex
    3804 microseconds per iteration # foreach + expr + lindex
    2739 microseconds per iteration # while

最新回答 9月 22, 2015 用户: 风行水上 (-30 分)
0 投票

从字节码(Byte Code)角度看for和foreach的分别。

字节码: Tcl 8.5.2
ByteCode 0x0xe5b68f0, refCt 1, epoch 3, interp 0x0xe5986a0 (epoch 3)
  Source "\n  for {set i 0} {$i<10} {incr i} {\n    set v [lindex $"
  Cmds 5, src 70, inst 62, litObjs 6, aux 0, stkDepth 3, code/src 0.00
  Exception ranges 2, depth 1:
      0: level 0, loop, pc 8-35, continue 37, break 59
      1: level 0, loop, pc 37-49, continue -1, break 59
  Commands 5:
      1: pc 0-60, src 3-68         2: pc 0-4, src 8-14
      3: pc 8-35, src 40-64        4: pc 19-34, src 47-63
      5: pc 37-49, src 26-31
  Command 1: "for {set i 0} {$i<10} {incr i} {\n    set v [lindex $val"
  Command 2: "set i 0"
    (0) push1 0         # "i"
    (2) push1 1         # "0"
    (4) storeScalarStk
    (5) pop
    (6) jump1 +45       # pc 51
  Command 3: "set v [lindex $values $i]"
    (8) startCommand +28 1      # next cmd at pc 36
    (17) push1 2        # "v"
  Command 4: "lindex $values $i"
    (19) startCommand +16 1     # next cmd at pc 35
    (28) push1 3        # "values"
    (30) loadScalarStk
    (31) push1 0        # "i"
    (33) loadScalarStk
    (34) listIndex
    (35) storeScalarStk
    (36) pop
  Command 5: "incr i"
    (37) startCommand +13 1     # next cmd at pc 50
    (46) push1 0        # "i"
    (48) incrScalarStkImm +1
    (50) pop
    (51) push1 0        # "i"
    (53) loadScalarStk
    (54) push1 4        # "10"
    (56) lt
    (57) jumpTrue1 -49  # pc 8
    (59) push1 5        # ""
    (61) done

ByteCode 0x0xe5c66e0, refCt 1, epoch 3, interp 0x0xe5986a0 (epoch 3)
  Source "\n  set i 0\n  foreach v $values {\n    incr i\n  }\n"
  Cmds 2, src 48, inst 18, litObjs 6, aux 0, stkDepth 4, code/src 0.00
  Commands 2:
      1: pc 0-5, src 3-9           2: pc 6-16, src 13-46
  Command 1: "set i 0"
    (0) push1 0         # "i"
    (2) push1 1         # "0"
    (4) storeScalarStk
    (5) pop
  Command 2: "foreach v $values {\n    incr i\n  }"
    (6) push1 2         # "foreach"
    (8) push1 3         # "v"
    (10) push1 4        # "values"
    (12) loadScalarStk
    (13) push1 5        # "\n    incr i\n  "
    (15) invokeStk1 4
    (17) done

字节码:Tcl 8.6
ByteCode 0x0xbaa8f60, refCt 1, epoch 15, interp 0x0xba1f680 (epoch 15)
  Source "\n  for {set i 0} {$i<10} {incr i} {\n    set v [lindex $"
  Cmds 5, src 70, inst 35, litObjs 6, aux 0, stkDepth 3, code/src 0.00
  Exception ranges 2, depth 1:
      0: level 0, loop, pc 8-17, continue 19, break 32
      1: level 0, loop, pc 19-22, continue -1, break 32
  Commands 5:
      1: pc 0-33, src 3-68        2: pc 0-4, src 8-14
      3: pc 8-17, src 40-64        4: pc 10-16, src 47-63
      5: pc 19-22, src 26-31
  Command 1: "for {set i 0} {$i<10} {incr i} {\n    set v [lindex $val"
  Command 2: "set i 0"
    (0) push1 0         # "i"
    (2) push1 1         # "0"
    (4) storeStk
    (5) pop
    (6) jump1 +18       # pc 24
  Command 3: "set v [lindex $values $i]"
    (8) push1 2         # "v"
  Command 4: "lindex $values $i"
    (10) push1 3        # "values"
    (12) loadStk
    (13) push1 0        # "i"
    (15) loadStk
    (16) listIndex
    (17) storeStk
    (18) pop
  Command 5: "incr i"
    (19) push1 0        # "i"
    (21) incrStkImm +1
    (23) pop
    (24) push1 0        # "i"
    (26) loadStk
    (27) push1 4        # "10"
    (29) lt
    (30) jumpTrue1 -22  # pc 8
    (32) push1 5        # ""
    (34) done

ByteCode 0x0xbaa8f60, refCt 1, epoch 15, interp 0x0xba1f680 (epoch 15)
  Source "\n  set i 0\n  foreach v $values {\n    incr i\n  }\n"
  Cmds 2, src 48, inst 18, litObjs 6, aux 0, stkDepth 4, code/src 0.00
  Commands 2:
      1: pc 0-5, src 3-9        2: pc 6-16, src 13-46
  Command 1: "set i 0"
    (0) push1 0         # "i"
    (2) push1 1         # "0"
    (4) storeStk
    (5) pop
  Command 2: "foreach v $values {\n    incr i\n  }"
    (6) push1 2         # "foreach"
    (8) push1 3         # "v"
    (10) push1 4        # "values"
    (12) loadStk
    (13) push1 5        # "\n    incr i\n  "
    (15) invokeStk1 4
    (17) done


最新回答 9月 22, 2015 用户: 风行水上 (-30 分)
for和foreach编译成字节码之后的速度比较
...