Mercurial > public > mercurial-scm > hg
comparison mercurial/context.py @ 27906:c183f7b79541
context: don't use util.cachefunc due to cycle creation (issue5043)
util.cachefunc stores all arguments as the cache key. For filectxfn
functions, the arguments include the memctx instance. This creates a
cycle where memctx._filectxfn references self. This causes a memory
leak.
We break the cycle by implementing our own memoizing function that
only uses the path as the cache key. Since each memctx has its own
cache instance, there is no concern about invalid cache hits.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 17 Jan 2016 12:10:30 -0800 |
parents | ff20fe74e5c6 |
children | 75fa75d31495 |
comparison
equal
deleted
inserted
replaced
27905:27f2f5c1d499 | 27906:c183f7b79541 |
---|---|
1777 changed = set(self._status.modified) | 1777 changed = set(self._status.modified) |
1778 changed.update(self._status.added) | 1778 changed.update(self._status.added) |
1779 changed.update(self._status.removed) | 1779 changed.update(self._status.removed) |
1780 return changed | 1780 return changed |
1781 | 1781 |
1782 def makecachingfilectxfn(func): | |
1783 """Create a filectxfn that caches based on the path. | |
1784 | |
1785 We can't use util.cachefunc because it uses all arguments as the cache | |
1786 key and this creates a cycle since the arguments include the repo and | |
1787 memctx. | |
1788 """ | |
1789 cache = {} | |
1790 | |
1791 def getfilectx(repo, memctx, path): | |
1792 if path not in cache: | |
1793 cache[path] = func(repo, memctx, path) | |
1794 return cache[path] | |
1795 | |
1796 return getfilectx | |
1797 | |
1782 class memctx(committablectx): | 1798 class memctx(committablectx): |
1783 """Use memctx to perform in-memory commits via localrepo.commitctx(). | 1799 """Use memctx to perform in-memory commits via localrepo.commitctx(). |
1784 | 1800 |
1785 Revision information is supplied at initialization time while | 1801 Revision information is supplied at initialization time while |
1786 related files data and is made available through a callback | 1802 related files data and is made available through a callback |
1836 return memfilectx(repo, path, fctx.data(), | 1852 return memfilectx(repo, path, fctx.data(), |
1837 islink=fctx.islink(), isexec=fctx.isexec(), | 1853 islink=fctx.islink(), isexec=fctx.isexec(), |
1838 copied=copied, memctx=memctx) | 1854 copied=copied, memctx=memctx) |
1839 self._filectxfn = getfilectx | 1855 self._filectxfn = getfilectx |
1840 else: | 1856 else: |
1841 # "util.cachefunc" reduces invocation of possibly expensive | 1857 # memoizing increases performance for e.g. vcs convert scenarios. |
1842 # "filectxfn" for performance (e.g. converting from another VCS) | 1858 self._filectxfn = makecachingfilectxfn(filectxfn) |
1843 self._filectxfn = util.cachefunc(filectxfn) | |
1844 | 1859 |
1845 if extra: | 1860 if extra: |
1846 self._extra = extra.copy() | 1861 self._extra = extra.copy() |
1847 else: | 1862 else: |
1848 self._extra = {} | 1863 self._extra = {} |