summaryrefslogtreecommitdiff
path: root/.mailmap
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2021-02-11 00:56:56 -0800
committerGreg Becker <becker33@llnl.gov>2021-03-31 14:39:23 -0700
commit01a6adb5f7d6771150ff01c8ceb413519de0eccf (patch)
tree03ab5109ba67031be84691ebdcc685efb0db99e9 /.mailmap
parentfd12cba18b79f1808f317f22672e2b7a8b385536 (diff)
downloadspack-01a6adb5f7d6771150ff01c8ceb413519de0eccf.tar.gz
spack-01a6adb5f7d6771150ff01c8ceb413519de0eccf.tar.bz2
spack-01a6adb5f7d6771150ff01c8ceb413519de0eccf.tar.xz
spack-01a6adb5f7d6771150ff01c8ceb413519de0eccf.zip
specs: use lazy lexicographic comparison instead of key_ordering
We have been using the `@llnl.util.lang.key_ordering` decorator for specs and most of their components. This leverages the fact that in Python, tuple comparison is lexicographic. It allows you to implement a `_cmp_key` method on your class, and have `__eq__`, `__lt__`, etc. implemented automatically using that key. For example, you might use tuple keys to implement comparison, e.g.: ```python class Widget: # author implements this def _cmp_key(self): return ( self.a, self.b, (self.c, self.d), self.e ) # operators are generated by @key_ordering def __eq__(self, other): return self._cmp_key() == other._cmp_key() def __lt__(self): return self._cmp_key() < other._cmp_key() # etc. ``` The issue there for simple comparators is that we have to bulid the tuples *and* we have to generate all the values in them up front. When implementing comparisons for large data structures, this can be costly. This PR replaces `@key_ordering` with a new decorator, `@lazy_lexicographic_ordering`. Lazy lexicographic comparison maps the tuple comparison shown above to generator functions. Instead of comparing based on pre-constructed tuple keys, users of this decorator can compare using elements from a generator. So, you'd write: ```python @lazy_lexicographic_ordering class Widget: def _cmp_iter(self): yield a yield b def cd_fun(): yield c yield d yield cd_fun yield e # operators are added by decorator (but are a bit more complex) There are no tuples that have to be pre-constructed, and the generator does not have to complete. Instead of tuples, we simply make functions that lazily yield what would've been in the tuple. If a yielded value is a `callable`, the comparison functions will call it and recursively compar it. The comparator just walks the data structure like you'd expect it to. The ``@lazy_lexicographic_ordering`` decorator handles the details of implementing comparison operators, and the ``Widget`` implementor only has to worry about writing ``_cmp_iter``, and making sure the elements in it are also comparable. Using this PR shaves another 1.5 sec off the runtime of `spack buildcache list`, and it also speeds up Spec comparison by about 30%. The runtime improvement comes mostly from *not* calling `hash()` `_cmp_iter()`.
Diffstat (limited to '.mailmap')
0 files changed, 0 insertions, 0 deletions