changeset 16404:9fca5b056c0a

store: speed up read and write of large fncache files In my tests of an fncache containing 300,000 entries, this improves read time from 567ms to 307, and write time from 1328ms to 533. These numbers aren't so great, since the fncache file is only 17MB in size, but they're an improvement.
author Bryan O'Sullivan <bryano@fb.com>
date Thu, 12 Apr 2012 15:21:54 -0700
parents efae1fea4bbd
children 17deb6bbfbab
files mercurial/store.py
diffstat 1 files changed, 18 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/store.py	Thu Apr 12 15:21:52 2012 -0700
+++ b/mercurial/store.py	Thu Apr 12 15:21:54 2012 -0700
@@ -317,36 +317,36 @@
 
     def _load(self):
         '''fill the entries from the fncache file'''
-        self.entries = set()
         self._dirty = False
         try:
             fp = self.opener('fncache', mode='rb')
         except IOError:
             # skip nonexistent file
+            self.entries = set()
             return
-        for n, line in enumerate(fp):
-            if (len(line) < 2) or (line[-1] != '\n'):
-                t = _('invalid entry in fncache, line %s') % (n + 1)
-                raise util.Abort(t)
-            self.entries.add(decodedir(line[:-1]))
+        self.entries = set(map(decodedir, fp.read().splitlines()))
+        if '' in self.entries:
+            fp.seek(0)
+            for n, line in enumerate(fp):
+                if not line.rstrip('\n'):
+                    t = _('invalid entry in fncache, line %s') % (n + 1)
+                    raise util.Abort(t)
         fp.close()
 
+    def _write(self, files, atomictemp):
+        fp = self.opener('fncache', mode='wb', atomictemp=atomictemp)
+        if files:
+            fp.write('\n'.join(map(encodedir, files)) + '\n')
+        fp.close()
+        self._dirty = False
+
     def rewrite(self, files):
-        fp = self.opener('fncache', mode='wb')
-        for p in files:
-            fp.write(encodedir(p) + '\n')
-        fp.close()
+        self._write(files, False)
         self.entries = set(files)
-        self._dirty = False
 
     def write(self):
-        if not self._dirty:
-            return
-        fp = self.opener('fncache', mode='wb', atomictemp=True)
-        for p in self.entries:
-            fp.write(encodedir(p) + '\n')
-        fp.close()
-        self._dirty = False
+        if self._dirty:
+            self._write(self.entries, True)
 
     def add(self, fn):
         if self.entries is None: