2016-09-27 118 views
1

在TCL中,大致可以通過global varname訪問全局變量,或者通過namespace varname命令訪問命名空間變量。
我對2的訪問時間非常簡單的檢查顯示,對於版本爲tcl 8.5的版本,variableglobal的運行時訪問優勢很小但一致。
我們可以預計8.6和更高的情況是如此,至少現在呢?TCL全局訪問速度與可變訪問速度

+0

你能告訴我們你是如何測試它的?你有什麼不同? –

+0

我只設置了2個變量,一個名字空間,一個全局變量。 然後我有2個名稱空間過程,它聲明變量(一個全局的,另一個名字空間),然後返回值。然後我用了100000次迭代的時間命令。在我的系統上,差異在運行時一直保持在〜0.8%,命名空間稍快。 – user1134991

回答

3

TL;博士:有兩者之間的速度非常差別不大,不夠的,你應該關心。以一種在語義上正確的方式來做事情,並將其留在那裏。正確的爲您的使用案例將擊敗任何修補百分比在時間上的百分比。


讓我們以下兩個過程比較全局命名空間做同樣的事情。請注意,我們正在比較的選項之間的差異的權重將相對於真實代碼被人爲地提高;這些都是微觀基準,應該被懷疑地對待。

proc a {} { 
    global x y 
    expr {$x + $y} 
} 

proc b {} { 
    variable x 
    variable y 
    expr {$x + $y} 
} 

OK,時序信息(絕對的時序根據硬件不同):

% set x 123 
123 
% set y 456 
456 
% a 
579 
% b 
579 
% time { a } 10000 
0.5720533 microseconds per iteration 
% time { b } 10000 
0.5756787999999999 microseconds per iteration 

所以,是的,ba稍微慢一些。讓我們來看看字節碼就能明白爲什麼

% tcl::unsupported::disassemble proc a 
ByteCode 0x0x10280fe10, refCt 1, epoch 15, interp 0x0x100829a10 (epoch 15) 
    Source "\n global x y\n expr {$x + $y"... 
    Cmds 2, src 35, inst 35, litObjs 4, aux 0, stkDepth 2, code/src 0.00 
    Proc 0x0x102822c10, refCt 1, args 0, compiled locals 2 
     slot 0, scalar, "x" 
     slot 1, scalar, "y" 
    Commands 2: 
     1: pc 0-19, src 5-14  2: pc 20-33, src 20-33 
    Command 1: "global x y"... 
    (0) push1 0  # "::" 
    (2) push1 1  # "x" 
    (4) nsupvar %v0  # var "x" 
    (9) push1 2  # "y" 
    (11) nsupvar %v1 # var "y" 
    (16) pop 
    (17) nop 
    (18) nop 
    (19) nop 
    Command 2: "expr {$x + $y}"... 
    (20) startCommand +14 1  # next cmd at pc 34, 1 cmds start here 
    (29) loadScalar1 %v0 # var "x" 
    (31) loadScalar1 %v1 # var "y" 
    (33) add 
    (34) done 

% tcl::unsupported::disassemble proc b 
ByteCode 0x0x10280fa10, refCt 1, epoch 15, interp 0x0x100829a10 (epoch 15) 
    Source "\n variable x\n variable y\n expr {$x + $"... 
    Cmds 3, src 50, inst 44, litObjs 3, aux 0, stkDepth 2, code/src 0.00 
    Proc 0x0x102822a90, refCt 1, args 0, compiled locals 2 
     slot 0, scalar, "x" 
     slot 1, scalar, "y" 
    Commands 3: 
     1: pc 0-9, src 5-14  2: pc 10-28, src 20-29 
     3: pc 29-42, src 35-48 
    Command 1: "variable x"... 
    (0) push1 0  # "x" 
    (2) variable %v0 # var "x" 
    (7) nop 
    (8) nop 
    (9) nop 
    Command 2: "variable y"... 
    (10) startCommand +18 1  # next cmd at pc 28, 1 cmds start here 
    (19) push1 2 # "y" 
    (21) variable %v1 # var "y" 
    (26) push1 1 # "" 
    (28) pop 
    Command 3: "expr {$x + $y}"... 
    (29) startCommand +14 1  # next cmd at pc 43, 1 cmds start here 
    (38) loadScalar1 %v0 # var "x" 
    (40) loadScalar1 %v1 # var "y" 
    (42) add 
    (43) done 

確切的字節序列可能對你的Tcl的版本不同;這完全是實現的一部分,而不是官方的界面。但是,我們可以看到,使用global的操作碼序列涉及一個名稱空間句柄的單個push1以及兩個nsupvars在該命令的執行內部,並且使用兩個variable調用,名稱空間不被推送,但是variable操作碼被使用兩次兩者之間還有額外的startCommandstartCommand是一個混亂的基礎設施,有抑制一些次要優化的副作用,所以這可能是原因。

兩者之間這樣小的差異,制定出在性能上的差異確實是將需要的儀器一樣cachegrind ...

順便說一句,儘量表現與此對比:

proc c {} { 
    namespace upvar :: x x y y 
    expr {$x + $y} 
} 

那有一個完全相同的字節碼序列到上面的a程序...