2016-08-20 13 views

回答

4

表現。

考慮這個微小的風向標:

#lang racket/base 

(require racket/sequence) 

(define len 10000) 
(define vec (make-vector len)) 

(collect-garbage) 
(collect-garbage) 
(collect-garbage) 

(time (void (for/list ([i (in-range len)]) 
       (vector-ref vec i)))) 

(collect-garbage) 
(collect-garbage) 
(collect-garbage) 

(time (void (for/list ([i (in-range len)]) 
       (sequence-ref vec i)))) 

這是我的機器上輸出:

; vectors (vector-ref vs sequence-ref) 
cpu time: 1 real time: 1 gc time: 0 
cpu time: 2082 real time: 2081 gc time: 0 

是的,這是幅度的3個數量級的差別。

爲什麼?那麼,racket/sequence不是一個非常「聰明」的API,即使向量是隨機訪問,sequence-ref不是。結合Racket優化器大量優化原始操作的能力,序列API是一個相當差的接口。

當然,這是有點不公平的,因爲載體是隨機存取的,而像列表這樣的東西不是。但是,執行完全相同的測試與上述一個,但使用列表代替矢量仍產生一個相當嚴酷的結果:

; lists (list-ref vs sequence-ref) 
cpu time: 113 real time: 113 gc time: 0 
cpu time: 1733 real time: 1732 gc time: 0 

序列API是,大多高電平間接的,因爲。

現在,單憑性能並不是完全拒絕API的理由,因爲在更高級別的抽象層次上工作有具體優勢。這就是說,我認爲序列API是不是一個很好的抽象,因爲它:

  1. ...不必要地在實施,這使該接口的實現造成不必要的負擔有狀態的。

  2. ...不適合與列表不相似的東西,例如隨機訪問向量或散列表。

如果你想用一個更高層次的API的工作,一個可能的選擇是使用collections package,它試圖提供類似racket/sequence的API,但容納多種數據結構,並且還具有更完整功能集。 免責聲明:我是collections軟件包的作者。

鑑於上述基準一次,表現仍然不是直接使用基本功能差,但它至少有點更易於管理:

; vectors (vector-ref vs ref) 
cpu time: 2 real time: 1 gc time: 0 
cpu time: 97 real time: 98 gc time: 10 

; lists (list-ref vs ref) 
cpu time: 104 real time: 103 gc time: 0 
cpu time: 481 real time: 482 gc time: 0 

無論你能承受的開銷取決於你究竟在做什麼,取決於你自己打電話。只要執行某種動態調度,專門的操作總是比那些遵守它們的程序至少稍微快一些。像往常一樣,記住性能優化的規則:不要猜測,測量。

+0

在(時間...)功能之間有(收集 - 垃圾)是必不可少的嗎? – rnso

相關問題