Ich kam in diesem während einig Performance-sensitiven Code-Tuning:Warum wird get-in langsamer als durchgefädelt?
user> (use 'criterium.core)
nil
user> (def n (into {} (for [i (range 20000) :let [k (keyword (str i))]] [k {k k}])))
#'user/n
user> (quick-bench (-> n :1 :1))
WARNING: Final GC required 32.5115186521176 % of runtime
Evaluation count : 15509754 in 6 samples of 2584959 calls.
Execution time mean : 36.256135 ns
Execution time std-deviation : 1.076403 ns
Execution time lower quantile : 35.120871 ns (2.5%)
Execution time upper quantile : 37.470993 ns (97.5%)
Overhead used : 1.755171 ns
nil
user> (quick-bench (get-in n [:1 :1]))
WARNING: Final GC required 33.11057826481865 % of runtime
Evaluation count : 7681728 in 6 samples of 1280288 calls.
Execution time mean : 81.023429 ns
Execution time std-deviation : 3.244516 ns
Execution time lower quantile : 78.220643 ns (2.5%)
Execution time upper quantile : 85.906898 ns (97.5%)
Overhead used : 1.755171 ns
nil
Es ist mir nicht intuitiv, dass get-in
zweimal mehr ist, als so langsam wie durch get
Einfädeln s hier als get-in
scheint als die bessere Abstraktion für diese definiert werden irgendwie.
Hat jemand einen Einblick, warum dies der Fall ist (sowohl technisch als auch philosophisch)?
Wenn Sie an der Quelle für diese beiden Funktionen anschaut, kann man sehen, dass es einige Rekursion in los [ 'get-in'] (https://github.com/clojure/clojure/blob/clojure-1.7.0 /src/clj/clojure/core.clj#L5882), die es ermöglicht, verschachtelte Strukturen zu durchforsten. Ich schätze, das ist die Ursache für den zusätzlichen Overhead. – jmargolisvt
Ich kann nur raten, dass Get-In eine "Allzweck" -Funktion ist und mehr Overhead hat. Auf meinem Computer ist es nicht ganz so schlimm, bei 31 ns vs 57 ns. –