summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-13 14:58:54 -0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-13 14:58:54 -0400
commit3e89ef597ce00dbf82a937aad9efab3c9c7b6dcf (patch)
tree60d4896f8c8b063ce7d2354fb357da9a2a13c0ba
parent9c2d63084bd4f6a04210cd52b4fce054d248bc6b (diff)
downloadguix-3e89ef597ce00dbf82a937aad9efab3c9c7b6dcf.tar.gz
Optimise concatenating a list to an empty list
More precisely, in concatLists, if all lists except one are empty,
then just return the non-empty list.  This reduces the number of list
element allocations by 32% when evaluating a NixOS system
configuration.
-rw-r--r--src/libexpr/eval.cc12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 5351ca0c34..517a1151ec 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -922,11 +922,19 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
 void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists)
 {
     nrListConcats++;
-    
+
+    Value * nonEmpty = 0;
     unsigned int len = 0;
     for (unsigned int n = 0; n < nrLists; ++n) {
         forceList(*lists[n]);
-        len += lists[n]->list.length;
+        unsigned int l = lists[n]->list.length;
+        len += l;
+        if (l) nonEmpty = lists[n];
+    }
+
+    if (nonEmpty && len == nonEmpty->list.length) {
+        v = *nonEmpty;
+        return;
     }
 
     mkList(v, len);