Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Clojure by
edited by

So for a relatively small xrel with relatively few renames, there seems to be some performance gains to be had:

user> (def xrel {:a 1, :b 2, :c 3})
;; => #'user/xrel
user> (def kmap {:a :z})
;; => #'user/kmap
user> (quick-bench (set/rename-keys xrel kmap))
Evaluation count : 2959512 in 6 samples of 493252 calls.
         Execution time mean : 200.870412 ns
Execution time std-deviation : 0.882651 ns
Execution time lower quantile : 200.116289 ns ( 2.5%)
Execution time upper quantile : 202.248092 ns (97.5%)
               Overhead used : 2.151518 ns

Found 1 outliers in 6 samples (16.6667 %)
low-severe	 1 (16.6667 %)
Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
;; => nil
user> (quick-bench (set/rename-keys2 xrel kmap))
Evaluation count : 9627438 in 6 samples of 1604573 calls.
         Execution time mean : 59.646747 ns
Execution time std-deviation : 0.083186 ns
Execution time lower quantile : 59.540415 ns ( 2.5%)
Execution time upper quantile : 59.723488 ns (97.5%)
                Overhead used : 2.151518 ns
;; => nil
user> 

For set/rename-keys2 defined as

(defn rename-keys2
  "Returns the map with the keys in kmap renamed to the vals in kmap"
  {:added "1.0"}
  [map kmap]
  (reduce-kv
   (fn [m old new]
     (if (contains? map old)
       (-> m
           (assoc new (get map old))
           (dissoc old))
       m)) map kmap))

Would something along these lines be interesting as a start for an investigation into improving rename-keys?

1 Answer

0 votes
by

I think I'd start with trying to build on update-keys before anything else.

by
I think that would be something like

(defn rename-keys [m km] (update-keys m #(get km % %)))
by
There is a subtle difference insofar that `update-keys` always return a map, also for `nil`,  whereas `set/rename-keys` return nil for nil.

Also, the `update-keys` version seems (surprisingly) a bit slower:

user> (quick-bench (clojure.set/rename-keys2 xrel kmap))
Evaluation count : 9637890 in 6 samples of 1606315 calls.
             Execution time mean : 59.522351 ns
    Execution time std-deviation : 0.059405 ns
   Execution time lower quantile : 59.452942 ns ( 2.5%)
   Execution time upper quantile : 59.580547 ns (97.5%)
                   Overhead used : 2.151518 ns
;; => nil
user> (quick-bench (clojure.set/rename-keys3 xrel kmap))
Evaluation count : 5567220 in 6 samples of 927870 calls.
             Execution time mean : 106.542514 ns
    Execution time std-deviation : 1.114478 ns
   Execution time lower quantile : 105.393362 ns ( 2.5%)
   Execution time upper quantile : 107.800880 ns (97.5%)
                   Overhead used : 2.151518 ns
;; => nil
by
It's hard to make a speed comparison like this given a map with a single key processed a bunch of times. While, `update-keys` might be slower in general, some thought needs to go into thinking about the profile of the typical use case for `rename-keys`. In the case of `update-keys` we determined that the need usually manifests in server applications that send and receive info packets or deal with entity maps and need to perform transformations on the keys as a whole -- typically to turn string keys into keywords and back again.
...