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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.