From: "Karl Hasselström" <kha@treskal.com>
To: Catalin Marinas <catalin.marinas@gmail.com>
Cc: git@vger.kernel.org
Subject: [StGit PATCH 2/2] Reuse the same temp index in a transaction
Date: Wed, 02 Jul 2008 08:13:15 +0200 [thread overview]
Message-ID: <20080702061314.11361.28297.stgit@yoghurt> (raw)
In-Reply-To: <20080702060113.11361.39006.stgit@yoghurt>
Instead of making a new temp index every time we need one, just keep
reusing the same one. And keep track of which tree is currently stored
in it -- if we do several consecutive successful pushes, it's always
going to be the "right" tree so that we don't have to call read-tree
before each patch application.
The motivation behind this change is of course that it makes things
faster.
(The same simple test as in the previous patch -- pushing 250 patches
in a 32k-file repository, with one file-level merge necessary per push
-- went from 0.36 to 0.19 seconds per patch with this patch applied.)
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/lib/git.py | 43 +++++++++++++++++++++++++++++--------------
stgit/lib/transaction.py | 12 +++++++++++-
2 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index a38eaa5..c98e919 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -459,31 +459,46 @@ class Repository(RunWithEnv):
def set_head_ref(self, ref, msg):
self.run(['git', 'symbolic-ref', '-m', msg, 'HEAD', ref]).no_output()
def simple_merge(self, base, ours, theirs):
+ index = self.temp_index()
+ try:
+ result, index_tree = self.index_merge(base, ours, theirs,
+ index, None)
+ finally:
+ index.delete()
+ return result
+ def index_merge(self, base, ours, theirs, index, current):
"""Given three L{Tree}s, tries to do an in-index merge with a
- temporary index. Returns the result L{Tree}, or None if the
- merge failed (due to conflicts)."""
+ temporary index. Returns a pair: the result L{Tree}, or None
+ if the merge failed (due to conflicts); and the L{Tree} now
+ stored in the index.
+
+ C{index} is the L{Index} object to use for the merge.
+ C{current} is the L{Tree} object currently stored in the given
+ index. If this is the same as C{ours}, some work is saved.
+ (C{current} may be C{None}, in which case this optimization is
+ disabled.)"""
assert isinstance(base, Tree)
assert isinstance(ours, Tree)
assert isinstance(theirs, Tree)
+ assert isinstance(index, Index)
+ assert current == None or isinstance(current, Tree)
# Take care of the really trivial cases.
if base == ours:
- return theirs
+ return (theirs, current)
if base == theirs:
- return ours
+ return (ours, current)
if ours == theirs:
- return ours
+ return (ours, current)
- index = self.temp_index()
- index.read_tree(ours)
+ if current != ours:
+ index.read_tree(ours)
try:
- try:
- index.apply_treediff(base, theirs)
- return index.write_tree()
- except MergeException:
- return None
- finally:
- index.delete()
+ index.apply_treediff(base, theirs)
+ result = index.write_tree()
+ return result, result
+ except MergeException:
+ return None, ours
def apply(self, tree, patch_text):
"""Given a L{Tree} and a patch, will either return the new L{Tree}
that results when the patch is applied, or None if the patch
diff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py
index e47997e..b4d4b75 100644
--- a/stgit/lib/transaction.py
+++ b/stgit/lib/transaction.py
@@ -1,6 +1,8 @@
"""The L{StackTransaction} class makes it possible to make complex
updates to an StGit stack in a safe and convenient way."""
+import atexit
+
from stgit import exception, utils
from stgit.utils import any, all
from stgit.out import *
@@ -84,6 +86,7 @@ class StackTransaction(object):
self.__allow_conflicts = lambda trans: allow_conflicts
else:
self.__allow_conflicts = allow_conflicts
+ self.__temp_index = self.temp_index_tree = None
stack = property(lambda self: self.__stack)
patches = property(lambda self: self.__patches)
def __set_applied(self, val):
@@ -97,6 +100,12 @@ class StackTransaction(object):
or self.patches[self.applied[0]].data.parent == val)
self.__base = val
base = property(lambda self: self.__base, __set_base)
+ @property
+ def temp_index(self):
+ if not self.__temp_index:
+ self.__temp_index = self.__stack.repository.temp_index()
+ atexit.register(self.__temp_index.delete)
+ return self.__temp_index
def __checkout(self, tree, iw):
if not self.__stack.head_top_equal():
out.error(
@@ -238,7 +247,8 @@ class StackTransaction(object):
base = oldparent.data.tree
ours = cd.parent.data.tree
theirs = cd.tree
- tree = self.__stack.repository.simple_merge(base, ours, theirs)
+ tree, self.temp_index_tree = self.__stack.repository.index_merge(
+ base, ours, theirs, self.temp_index, self.temp_index_tree)
merge_conflict = False
if not tree:
if iw == None:
next prev parent reply other threads:[~2008-07-02 6:21 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-02 6:12 [StGit PATCH 0/2] push optimizations Karl Hasselström
2008-07-02 6:12 ` [StGit PATCH 1/2] Do simple in-index merge with diff+apply instead of read-tree Karl Hasselström
2008-07-12 10:22 ` Catalin Marinas
2008-07-02 6:13 ` Karl Hasselström [this message]
2008-07-03 21:38 ` [StGit PATCH v2] Reuse the same temp index in a transaction Karl Hasselström
2008-07-12 10:24 ` [StGit PATCH 2/2] " Catalin Marinas
2008-07-14 6:35 ` Karl Hasselström
2008-07-07 21:12 ` [StGit PATCH 0/2] push optimizations Catalin Marinas
2008-07-08 4:36 ` Karl Hasselström
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080702061314.11361.28297.stgit@yoghurt \
--to=kha@treskal.com \
--cc=catalin.marinas@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).