2016-08-20 3 views

答えて

4

パフォーマンス。

は、この小さなベンチマークを考えてみましょう:

; 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桁の違いがあります:

#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)))) 

これは私のマシン上に出力されています。

なぜですか?まあ、racket/sequenceはひどく "スマートな" APIではないし、ベクトルがランダムアクセスであっても、sequence-refはそうではない。ラケットオプティマイザがプリミティブ操作を大幅に最適化する機能と組み合わせることで、シーケンスAPIは非常に貧弱なインターフェースになります。

もちろん、ベクトルはランダムなアクセスであり、リストのようなものはそうではないので、これは少し不公平です。ただし、上記1とまったく同じテストを実行する代わりに、ベクトルのリストを使用すると、まだかなり厳しい結果が得られます。

; 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を完全に拒否するわけではありません。

  1. ...不インタフェースの実装に不要な負担をかけ、その実装、ステートフルされています。それはそれはので、私は、シーケンスのAPIが良い抽象化はないと思う、と述べました。

  2. ...ランダムアクセスベクターやハッシュテーブルなど、リストに似ていないものには対応していません。

あなたがより高いレベルのAPIで作業したい場合は、一つの可能​​なオプションがracket/sequenceに似たAPIを提供しようとする、collections packageを使用することであるが、データ構造の種類以上を収容し、また、より完全持ちます機能のセット。 免責事項:私は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

関連する問題