Created
March 14, 2012 12:08
-
-
Save ato/2036052 to your computer and use it in GitHub Desktop.
Clojure startup time hack: refer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
clojure.core/refer is relatively heavyweight. It gets called 7 times during Clojure | |
startup (4 times in 1.3.0). There's potential to shave off 10% of the startup time | |
by improving it. Probably even more for projects with a large number of small | |
namespaces. | |
This is just a quick experiment to see what's possible, it would need much refining. | |
It's not thread safe, doesn't print warnings and could probably be written more | |
elegantly. | |
java -Xbootclasspath/a:clojure.jar -cp clojure.jar clojure.main -e "(System/exit 0)" | |
master: 0.56 user 0.03 system 0:00.44 elapsed 136% CPU 189264k maxresident | |
patch: 0.42 user 0.03 system 0:00.38 elapsed 118% CPU 178000k maxresident | |
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj | |
index e1aa2df..b747401 100644 | |
--- a/src/clj/clojure/core.clj | |
+++ b/src/clj/clojure/core.clj | |
@@ -3743,6 +3743,11 @@ | |
(= ns (.ns v)))) | |
(ns-map ns)))) | |
+(defn var-public? [ns ^clojure.lang.Var v] | |
+ (and (instance? clojure.lang.Var v) | |
+ (= ns (.ns v)) | |
+ (.isPublic v))) | |
+ | |
(defn refer | |
"refers to all public vars of ns, subject to filters. | |
filters can include at most one each of: | |
@@ -3759,7 +3764,22 @@ | |
to a symbol different from the var's name, in order to prevent | |
clashes. Use :use in the ns macro in preference to calling this directly." | |
{:added "1.0"} | |
- [ns-sym & filters] | |
+ ;; quick and dirty hack at a fast path version | |
+ ;; beware: not thread safe and doesn't give var redefined | |
+ ;; warnings. | |
+ ([ns-sym] | |
+ (let [ns (find-ns ns-sym) | |
+ nsmap (ns-map ns) | |
+ m (loop [src (ns-map ns) | |
+ dst (transient (.getMappings *ns*))] | |
+ (if-let [entry (first src)] | |
+ (let [sym (key entry) | |
+ v (val entry)] | |
+ (recur (rest src) (if (var-public? ns v) | |
+ (assoc! dst sym v) dst))) | |
+ dst))] | |
+ (.setMappings *ns* (persistent! m)))) | |
+ ([ns-sym & filters] | |
(let [ns (or (find-ns ns-sym) (throw (new Exception (str "No namespace: " ns-sym)))) | |
fs (apply hash-map filters) | |
nspublics (ns-publics ns) | |
@@ -3776,7 +3796,7 @@ | |
(if (get (ns-interns ns) sym) | |
(str sym " is not public") | |
(str sym " does not exist"))))) | |
- (. *ns* (refer (or (rename sym) sym) v))))))) | |
+ (. *ns* (refer (or (rename sym) sym) v)))))))) | |
(defn ns-refers | |
"Returns a map of the refer mappings for the namespace." | |
diff --git a/src/jvm/clojure/lang/Namespace.java b/src/jvm/clojure/lang/Namespace.java | |
index 0a4a38d..41aa2c6 100644 | |
--- a/src/jvm/clojure/lang/Namespace.java | |
+++ b/src/jvm/clojure/lang/Namespace.java | |
@@ -192,6 +192,10 @@ public Object getMapping(Symbol name){ | |
return mappings.get().valAt(name); | |
} | |
+public void setMappings(IPersistentMap map) { | |
+ mappings.set(map); | |
+} | |
+ | |
public Var findInternedVar(Symbol symbol){ | |
Object o = mappings.get().valAt(symbol); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment