Pickle parsed git config files

We now cache the output of `git config --list` for each of our
GitConfig instances in a Python pickle file.  These can be read
back in using only the Python interpreter at a much faster rate
than we can fork+exec the git config process.

If the corresponding git config file has a newer modification
timestamp than the pickle file, we delete the pickle file and
regenerate it.  This ensures that any edits made by the user
will be taken into account the next time we consult the file.

This reduces the time for a no-op repo sync from 0.847s to 0.269s.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce 2009-04-17 21:03:32 -07:00
parent fbcde472ca
commit c12c360f89

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import cPickle
import os import os
import re import re
import sys import sys
@ -57,6 +58,9 @@ class GitConfig(object):
self._cache_dict = None self._cache_dict = None
self._remotes = {} self._remotes = {}
self._branches = {} self._branches = {}
self._pickle = os.path.join(
os.path.dirname(self.file),
'.repopickle_' + os.path.basename(self.file))
def Has(self, name, include_defaults = True): def Has(self, name, include_defaults = True):
"""Return true if this configuration file has the key. """Return true if this configuration file has the key.
@ -170,6 +174,40 @@ class GitConfig(object):
return self._cache_dict return self._cache_dict
def _Read(self): def _Read(self):
d = self._ReadPickle()
if d is None:
d = self._ReadGit()
self._SavePickle(d)
return d
def _ReadPickle(self):
try:
if os.path.getmtime(self._pickle) \
<= os.path.getmtime(self.file):
os.remove(self._pickle)
return None
except OSError:
return None
try:
return cPickle.load(open(self._pickle, 'r'))
except IOError:
os.remove(self._pickle)
return None
except cPickle.PickleError:
os.remove(self._pickle)
return None
def _SavePickle(self, cache):
try:
cPickle.dump(cache,
open(self._pickle, 'w'),
cPickle.HIGHEST_PROTOCOL)
except IOError:
os.remove(self._pickle)
except cPickle.PickleError:
os.remove(self._pickle)
def _ReadGit(self):
d = self._do('--null', '--list') d = self._do('--null', '--list')
c = {} c = {}
while d: while d: