Mercurial > hg-stable
diff mercurial/util.py @ 34358:c41444a39de2
config: use copy-on-write to improve copy performance
Previously, chg's `verify` call could take 30+ms loading and checking new
config files. With one socket redirection, that adds up to around 70ms,
which is a lot for fast commands (ex. `bookmark --hidden`).
When investigating closer, A lot of time was spent on actually spent on ui
copying, which is mainly about `config.config` and `dict` copying.
This patch makes that 20x faster by adopting copy-on-write. The
copy-on-write is performed at config section level.
Before:
In [1]: %timeit ui.copy()
100 loops, best of 3: 2.32 ms per loop
After:
In [1]: %timeit ui.copy()
10000 loops, best of 3: 128 us per loop
2ms may look not that bad, but it adds up pretty quickly with multiple
calls. A typical chg run may call it 4 times, which is about 10ms.
Differential Revision: https://phab.mercurial-scm.org/D808
author | Jun Wu <quark@fb.com> |
---|---|
date | Wed, 27 Sep 2017 18:07:48 -0700 |
parents | 3bb2a9f25fe9 |
children | f435097d13c9 |
line wrap: on
line diff
--- a/mercurial/util.py Sat Sep 30 18:19:14 2017 +0530 +++ b/mercurial/util.py Wed Sep 27 18:07:48 2017 -0700 @@ -588,6 +588,24 @@ return f +class cow(object): + """helper class to make copy-on-write easier + + Call preparewrite before doing any writes. + """ + + def preparewrite(self): + """call this before writes, return self or a copied new object""" + if getattr(self, '_copied', 0): + self._copied -= 1 + return self.__class__(self) + return self + + def copy(self): + """always do a cheap copy""" + self._copied = getattr(self, '_copied', 0) + 1 + return self + class sortdict(collections.OrderedDict): '''a simple sorted dictionary @@ -613,6 +631,38 @@ for k, v in src: self[k] = v +class cowdict(cow, dict): + """copy-on-write dict + + Be sure to call d = d.preparewrite() before writing to d. + + >>> a = cowdict() + >>> a is a.preparewrite() + True + >>> b = a.copy() + >>> b is a + True + >>> c = b.copy() + >>> c is a + True + >>> a = a.preparewrite() + >>> b is a + False + >>> a is a.preparewrite() + True + >>> c = c.preparewrite() + >>> b is c + False + >>> b is b.preparewrite() + True + """ + +class cowsortdict(cow, sortdict): + """copy-on-write sortdict + + Be sure to call d = d.preparewrite() before writing to d. + """ + class transactional(object): """Base class for making a transactional type into a context manager.""" __metaclass__ = abc.ABCMeta