{"thread":{"id":"14249","subject":"[StGit PATCH 0/2] push optimizations","startedAt":"2008-07-02T06:12:06Z","lastAt":"2008-07-14T06:35:51Z","messageCount":9,"participants":["Karl Hasselström","Catalin Marinas"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"81925","messageId":"20080702060113.11361.39006.stgit@yoghurt","threadId":"14249","inReplyTo":null,"subject":"[StGit PATCH 0/2] push optimizations","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-02T06:12:06Z","receivedAt":"2008-07-02T06:12:06Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"Here's the git-apply call you asked for. You were right: it was a huge\nspeed-up. I set up a benchmark to test it:\n\n  * 32 directories, each containing 32 subdirectories, each containing\n    32 small (and different) files.\n\n  * A series of 250 patches that each add a line to one of the files.\n\n  * An \"upstream\" that adds a line first in every file.\n\n  * I set all this up with a python script feeding fast-import. A huge\n    time-saver!\n\n  * Pop patches, git-reset to upstream, then goto top patch. This\n    makes sure that we use the new infrastructure to push, and that we\n    get one file-level conflict in each patch.\n\nBefore the first patch, the \"goto\" command took 4:27 minutes,\nwall-clock time. After the first patch, it took 1:31. After the\nsecond, 0:48; one second or so slower than the stable branch (which\ndoes not have a patch stack log).\n\nAvailable in kha/experimental.\n\n---\n\nKarl Hasselström (2):\n      Reuse the same temp index in a transaction\n      Do simple in-index merge with diff+apply instead of read-tree\n\n\n stgit/lib/git.py         |   52 +++++++++++++++++++++++++++++++---------------\n stgit/lib/transaction.py |   12 ++++++++++-\n 2 files changed, 46 insertions(+), 18 deletions(-)\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"81926","messageId":"20080702061243.11361.75544.stgit@yoghurt","threadId":"14249","inReplyTo":"20080702060113.11361.39006.stgit@yoghurt","subject":"[StGit PATCH 1/2] Do simple in-index merge with diff+apply instead of read-tree","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-02T06:12:44Z","receivedAt":"2008-07-02T06:12:44Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"The advantage is that patch application will resolve some file content\nconflicts for us, so that we'll fall back to merge-recursive less\noften. This is a significant speedup, especially since merge-recursive\nneeds to touch the worktree, which means we have to check out the\nindex first.\n\n(A simple test, pushing 250 patches in a 32k-file repository, with one\nfile-level merge necessary per push, went from 1.07 to 0.36 seconds\nper patch with this patch applied.)\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n\n---\n\n stgit/lib/git.py |   13 ++++++++-----\n 1 files changed, 8 insertions(+), 5 deletions(-)\n\n\ndiff --git a/stgit/lib/git.py b/stgit/lib/git.py\nindex 6ccdfa7..a38eaa5 100644\n--- a/stgit/lib/git.py\n+++ b/stgit/lib/git.py\n@@ -475,9 +475,10 @@ class Repository(RunWithEnv):\n             return ours\n \n         index = self.temp_index()\n+        index.read_tree(ours)\n         try:\n-            index.merge(base, ours, theirs)\n             try:\n+                index.apply_treediff(base, theirs)\n                 return index.write_tree()\n             except MergeException:\n                 return None\n@@ -548,10 +549,6 @@ class Index(RunWithEnv):\n             return False\n         else:\n             return True\n-    def merge(self, base, ours, theirs):\n-        \"\"\"In-index merge, no worktree involved.\"\"\"\n-        self.run(['git', 'read-tree', '-m', '-i', '--aggressive',\n-                  base.sha1, ours.sha1, theirs.sha1]).no_output()\n     def apply(self, patch_text):\n         \"\"\"In-index patch application, no worktree involved.\"\"\"\n         try:\n@@ -559,6 +556,12 @@ class Index(RunWithEnv):\n                      ).raw_input(patch_text).no_output()\n         except run.RunException:\n             raise MergeException('Patch does not apply cleanly')\n+    def apply_treediff(self, tree1, tree2):\n+        \"\"\"Apply the diff from C{tree1} to C{tree2} to the index.\"\"\"\n+        # Passing --full-index here is necessary to support binary\n+        # files. It is also sufficient, since the repository already\n+        # contains all involved objects.\n+        self.apply(self.__repository.diff_tree(tree1, tree2, ['--full-index']))\n     def delete(self):\n         if os.path.isfile(self.__filename):\n             os.remove(self.__filename)\n"},{"id":"81927","messageId":"20080702061314.11361.28297.stgit@yoghurt","threadId":"14249","inReplyTo":"20080702060113.11361.39006.stgit@yoghurt","subject":"[StGit PATCH 2/2] Reuse the same temp index in a transaction","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-02T06:13:15Z","receivedAt":"2008-07-02T06:13:15Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"Instead of making a new temp index every time we need one, just keep\nreusing the same one. And keep track of which tree is currently stored\nin it -- if we do several consecutive successful pushes, it's always\ngoing to be the \"right\" tree so that we don't have to call read-tree\nbefore each patch application.\n\nThe motivation behind this change is of course that it makes things\nfaster.\n\n(The same simple test as in the previous patch -- pushing 250 patches\nin a 32k-file repository, with one file-level merge necessary per push\n-- went from 0.36 to 0.19 seconds per patch with this patch applied.)\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n\n---\n\n stgit/lib/git.py         |   43 +++++++++++++++++++++++++++++--------------\n stgit/lib/transaction.py |   12 +++++++++++-\n 2 files changed, 40 insertions(+), 15 deletions(-)\n\n\ndiff --git a/stgit/lib/git.py b/stgit/lib/git.py\nindex a38eaa5..c98e919 100644\n--- a/stgit/lib/git.py\n+++ b/stgit/lib/git.py\n@@ -459,31 +459,46 @@ class Repository(RunWithEnv):\n     def set_head_ref(self, ref, msg):\n         self.run(['git', 'symbolic-ref', '-m', msg, 'HEAD', ref]).no_output()\n     def simple_merge(self, base, ours, theirs):\n+        index = self.temp_index()\n+        try:\n+            result, index_tree = self.index_merge(base, ours, theirs,\n+                                                  index, None)\n+        finally:\n+            index.delete()\n+        return result\n+    def index_merge(self, base, ours, theirs, index, current):\n         \"\"\"Given three L{Tree}s, tries to do an in-index merge with a\n-        temporary index. Returns the result L{Tree}, or None if the\n-        merge failed (due to conflicts).\"\"\"\n+        temporary index. Returns a pair: the result L{Tree}, or None\n+        if the merge failed (due to conflicts); and the L{Tree} now\n+        stored in the index.\n+\n+        C{index} is the L{Index} object to use for the merge.\n+        C{current} is the L{Tree} object currently stored in the given\n+        index. If this is the same as C{ours}, some work is saved.\n+        (C{current} may be C{None}, in which case this optimization is\n+        disabled.)\"\"\"\n         assert isinstance(base, Tree)\n         assert isinstance(ours, Tree)\n         assert isinstance(theirs, Tree)\n+        assert isinstance(index, Index)\n+        assert current == None or isinstance(current, Tree)\n \n         # Take care of the really trivial cases.\n         if base == ours:\n-            return theirs\n+            return (theirs, current)\n         if base == theirs:\n-            return ours\n+            return (ours, current)\n         if ours == theirs:\n-            return ours\n+            return (ours, current)\n \n-        index = self.temp_index()\n-        index.read_tree(ours)\n+        if current != ours:\n+            index.read_tree(ours)\n         try:\n-            try:\n-                index.apply_treediff(base, theirs)\n-                return index.write_tree()\n-            except MergeException:\n-                return None\n-        finally:\n-            index.delete()\n+            index.apply_treediff(base, theirs)\n+            result = index.write_tree()\n+            return result, result\n+        except MergeException:\n+            return None, ours\n     def apply(self, tree, patch_text):\n         \"\"\"Given a L{Tree} and a patch, will either return the new L{Tree}\n         that results when the patch is applied, or None if the patch\ndiff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py\nindex e47997e..b4d4b75 100644\n--- a/stgit/lib/transaction.py\n+++ b/stgit/lib/transaction.py\n@@ -1,6 +1,8 @@\n \"\"\"The L{StackTransaction} class makes it possible to make complex\n updates to an StGit stack in a safe and convenient way.\"\"\"\n \n+import atexit\n+\n from stgit import exception, utils\n from stgit.utils import any, all\n from stgit.out import *\n@@ -84,6 +86,7 @@ class StackTransaction(object):\n             self.__allow_conflicts = lambda trans: allow_conflicts\n         else:\n             self.__allow_conflicts = allow_conflicts\n+        self.__temp_index = self.temp_index_tree = None\n     stack = property(lambda self: self.__stack)\n     patches = property(lambda self: self.__patches)\n     def __set_applied(self, val):\n@@ -97,6 +100,12 @@ class StackTransaction(object):\n                 or self.patches[self.applied[0]].data.parent == val)\n         self.__base = val\n     base = property(lambda self: self.__base, __set_base)\n+    @property\n+    def temp_index(self):\n+        if not self.__temp_index:\n+            self.__temp_index = self.__stack.repository.temp_index()\n+            atexit.register(self.__temp_index.delete)\n+        return self.__temp_index\n     def __checkout(self, tree, iw):\n         if not self.__stack.head_top_equal():\n             out.error(\n@@ -238,7 +247,8 @@ class StackTransaction(object):\n         base = oldparent.data.tree\n         ours = cd.parent.data.tree\n         theirs = cd.tree\n-        tree = self.__stack.repository.simple_merge(base, ours, theirs)\n+        tree, self.temp_index_tree = self.__stack.repository.index_merge(\n+            base, ours, theirs, self.temp_index, self.temp_index_tree)\n         merge_conflict = False\n         if not tree:\n             if iw == None:\n"},{"id":"82162","messageId":"20080703213712.30489.51872.stgit@yoghurt","threadId":"14249","inReplyTo":"20080702061314.11361.28297.stgit@yoghurt","subject":"[StGit PATCH v2] Reuse the same temp index in a transaction","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-03T21:38:25Z","receivedAt":"2008-07-03T21:38:25Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"Instead of making a new temp index every time we need one, just keep\nreusing the same one. And keep track of which tree is currently stored\nin it -- if we do several consecutive successful pushes, it's always\ngoing to be the \"right\" tree so that we don't have to call read-tree\nbefore each patch application.\n\nThe motivation behind this change is of course that it makes things\nfaster.\n\n(The same simple test as in the previous patch -- pushing 250 patches\nin a 32k-file repository, with one file-level merge necessary per push\n-- went from 0.36 to 0.19 seconds per patch with this patch applied.)\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n\n---\n\nHere's the same patch, but with Repository.index_merge() instead\ncalled Index.merge(). A much better fit, I think.\n\nAlso some doc changes compared to v1.\n\n stgit/lib/git.py         |   63 +++++++++++++++++++++++++++++++---------------\n stgit/lib/transaction.py |   12 ++++++++-\n 2 files changed, 53 insertions(+), 22 deletions(-)\n\n\ndiff --git a/stgit/lib/git.py b/stgit/lib/git.py\nindex 9402606..8fb8bd2 100644\n--- a/stgit/lib/git.py\n+++ b/stgit/lib/git.py\n@@ -459,31 +459,12 @@ class Repository(RunWithEnv):\n     def set_head_ref(self, ref, msg):\n         self.run(['git', 'symbolic-ref', '-m', msg, 'HEAD', ref]).no_output()\n     def simple_merge(self, base, ours, theirs):\n-        \"\"\"Given three L{Tree}s, tries to do an in-index merge with a\n-        temporary index. Returns the result L{Tree}, or None if the\n-        merge failed (due to conflicts).\"\"\"\n-        assert isinstance(base, Tree)\n-        assert isinstance(ours, Tree)\n-        assert isinstance(theirs, Tree)\n-\n-        # Take care of the really trivial cases.\n-        if base == ours:\n-            return theirs\n-        if base == theirs:\n-            return ours\n-        if ours == theirs:\n-            return ours\n-\n         index = self.temp_index()\n-        index.read_tree(ours)\n         try:\n-            try:\n-                index.apply_treediff(base, theirs)\n-                return index.write_tree()\n-            except MergeException:\n-                return None\n+            result, index_tree = index.merge(base, ours, theirs)\n         finally:\n             index.delete()\n+        return result\n     def apply(self, tree, patch_text):\n         \"\"\"Given a L{Tree} and a patch, will either return the new L{Tree}\n         that results when the patch is applied, or None if the patch\n@@ -563,6 +544,46 @@ class Index(RunWithEnv):\n         # contains all involved objects; in other words, we don't have\n         # to use --binary.\n         self.apply(self.__repository.diff_tree(tree1, tree2, ['--full-index']))\n+    def merge(self, base, ours, theirs, current = None):\n+        \"\"\"Use the index (and only the index) to do a 3-way merge of the\n+        L{Tree}s C{base}, C{ours} and C{theirs}. The merge will either\n+        succeed (in which case the first half of the return value is\n+        the resulting tree) or fail cleanly (in which case the first\n+        half of the return value is C{None}).\n+\n+        If C{current} is given (and not C{None}), it is assumed to be\n+        the L{Tree} currently stored in the index; this information is\n+        used to avoid having to read the right tree (either of C{ours}\n+        and C{theirs}) into the index if it's already there. The\n+        second half of the return value is the tree now stored in the\n+        index, or C{None} if unknown. If the merge succeeded, this is\n+        often the merge result.\"\"\"\n+        assert isinstance(base, Tree)\n+        assert isinstance(ours, Tree)\n+        assert isinstance(theirs, Tree)\n+        assert current == None or isinstance(current, Tree)\n+\n+        # Take care of the really trivial cases.\n+        if base == ours:\n+            return (theirs, current)\n+        if base == theirs:\n+            return (ours, current)\n+        if ours == theirs:\n+            return (ours, current)\n+\n+        if current == theirs:\n+            # Swap the trees. It doesn't matter since merging is\n+            # symmetric, and will allow us to avoid the read_tree()\n+            # call below.\n+            ours, theirs = theirs, ours\n+        if current != ours:\n+            self.read_tree(ours)\n+        try:\n+            self.apply_treediff(base, theirs)\n+            result = self.write_tree()\n+            return (result, result)\n+        except MergeException:\n+            return (None, ours)\n     def delete(self):\n         if os.path.isfile(self.__filename):\n             os.remove(self.__filename)\ndiff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py\nindex e47997e..74bc74d 100644\n--- a/stgit/lib/transaction.py\n+++ b/stgit/lib/transaction.py\n@@ -1,6 +1,8 @@\n \"\"\"The L{StackTransaction} class makes it possible to make complex\n updates to an StGit stack in a safe and convenient way.\"\"\"\n \n+import atexit\n+\n from stgit import exception, utils\n from stgit.utils import any, all\n from stgit.out import *\n@@ -84,6 +86,7 @@ class StackTransaction(object):\n             self.__allow_conflicts = lambda trans: allow_conflicts\n         else:\n             self.__allow_conflicts = allow_conflicts\n+        self.__temp_index = self.temp_index_tree = None\n     stack = property(lambda self: self.__stack)\n     patches = property(lambda self: self.__patches)\n     def __set_applied(self, val):\n@@ -97,6 +100,12 @@ class StackTransaction(object):\n                 or self.patches[self.applied[0]].data.parent == val)\n         self.__base = val\n     base = property(lambda self: self.__base, __set_base)\n+    @property\n+    def temp_index(self):\n+        if not self.__temp_index:\n+            self.__temp_index = self.__stack.repository.temp_index()\n+            atexit.register(self.__temp_index.delete)\n+        return self.__temp_index\n     def __checkout(self, tree, iw):\n         if not self.__stack.head_top_equal():\n             out.error(\n@@ -238,7 +247,8 @@ class StackTransaction(object):\n         base = oldparent.data.tree\n         ours = cd.parent.data.tree\n         theirs = cd.tree\n-        tree = self.__stack.repository.simple_merge(base, ours, theirs)\n+        tree, self.temp_index_tree = self.temp_index.merge(\n+            base, ours, theirs, self.temp_index_tree)\n         merge_conflict = False\n         if not tree:\n             if iw == None:\n"},{"id":"82495","messageId":"b0943d9e0807071412j71780300p87d00cccea6cd8f4@mail.gmail.com","threadId":"14249","inReplyTo":"20080702060113.11361.39006.stgit@yoghurt","subject":"Re: [StGit PATCH 0/2] push optimizations","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2008-07-07T21:12:26Z","receivedAt":"2008-07-07T21:12:26Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"2008/7/2 Karl Hasselström <kha@treskal.com>:\n> Here's the git-apply call you asked for. You were right: it was a huge\n> speed-up.\n\nI know, I've been through this couple of years ago :-)\n\n> I set up a benchmark to test it:\n>\n>  * 32 directories, each containing 32 subdirectories, each containing\n>    32 small (and different) files.\n\nCan you try with a Linux kernel like the -mm tree? You get normally\nsized patches which might show a difference with the patch log. You\ncan clone the for-akpm branch on git://linux-arm.org/linux-2.6 and\njust uncommit ~300 patches.\n\n>  * I set all this up with a python script feeding fast-import. A huge\n>    time-saver!\n\nWhat is fast-import?\n\n>\n>  * Pop patches, git-reset to upstream, then goto top patch. This\n>    makes sure that we use the new infrastructure to push, and that we\n>    get one file-level conflict in each patch.\n>\n> Before the first patch, the \"goto\" command took 4:27 minutes,\n> wall-clock time. After the first patch, it took 1:31. After the\n> second, 0:48; one second or so slower than the stable branch (which\n> does not have a patch stack log).\n\nOne second is just noise and depends on how warm the caches are. You\ncould run a few times consecutively and discard the first result but\nwe don't need to be that accurate.\n\n-- \nCatalin\n"},{"id":"82545","messageId":"20080708043622.GC2247@diana.vm.bytemark.co.uk","threadId":"14249","inReplyTo":"b0943d9e0807071412j71780300p87d00cccea6cd8f4@mail.gmail.com","subject":"Re: [StGit PATCH 0/2] push optimizations","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-08T04:36:22Z","receivedAt":"2008-07-08T04:36:22Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2008-07-07 22:12:26 +0100, Catalin Marinas wrote:\n\n> 2008/7/2 Karl Hasselström <kha@treskal.com>:\n>\n> > Here's the git-apply call you asked for. You were right: it was a\n> > huge speed-up.\n>\n> I know, I've been through this couple of years ago :-)\n\n:-P\n\n> > I set up a benchmark to test it:\n> >\n> >  * 32 directories, each containing 32 subdirectories, each\n> >    containing 32 small (and different) files.\n>\n> Can you try with a Linux kernel like the -mm tree? You get normally\n> sized patches which might show a difference with the patch log. You\n> can clone the for-akpm branch on git://linux-arm.org/linux-2.6 and\n> just uncommit ~300 patches.\n\nSure, I'll do that. (But one of the reasons I chose a fully synthetic\nbenchmark is that I wanted to start a performance suite similar to our\ntest suite, and we want such a thing to be repeatable but not too\nlarge. (That said, operating on points of the kernel history that are\nfixed should do the trick as well. I'll try to find such points -- a\nlong string of -mm patches somewhere in the history maybe?))\n\n> >  * I set all this up with a python script feeding fast-import. A\n> >    huge time-saver!\n>\n> What is fast-import?\n\nman git-fast-import\n\nI'll try to clean up and publish the script I used.\n\n> >  * Pop patches, git-reset to upstream, then goto top patch. This\n> >    makes sure that we use the new infrastructure to push, and that\n> >    we get one file-level conflict in each patch.\n> >\n> > Before the first patch, the \"goto\" command took 4:27 minutes,\n> > wall-clock time. After the first patch, it took 1:31. After the\n> > second, 0:48; one second or so slower than the stable branch\n> > (which does not have a patch stack log).\n>\n> One second is just noise and depends on how warm the caches are. You\n> could run a few times consecutively and discard the first result but\n> we don't need to be that accurate.\n\nI did run a few times, and it did indeed fluctuate some -- but I'm\npretty sure there was a measurable slowdown. Though I agree that it's\nclose enough that it doesn't really make a difference.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"83069","messageId":"b0943d9e0807120322l350784b5sfceeb967f0956cdb@mail.gmail.com","threadId":"14249","inReplyTo":"20080702061243.11361.75544.stgit@yoghurt","subject":"Re: [StGit PATCH 1/2] Do simple in-index merge with diff+apply instead of read-tree","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2008-07-12T10:22:00Z","receivedAt":"2008-07-12T10:22:00Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"2008/7/2 Karl Hasselström <kha@treskal.com>:\n> The advantage is that patch application will resolve some file content\n> conflicts for us, so that we'll fall back to merge-recursive less\n> often. This is a significant speedup, especially since merge-recursive\n> needs to touch the worktree, which means we have to check out the\n> index first.\n\nThanks.\n\n-- \nCatalin\n"},{"id":"83070","messageId":"b0943d9e0807120324l7674c010w9a8e4a0bbdeeee65@mail.gmail.com","threadId":"14249","inReplyTo":"20080702061314.11361.28297.stgit@yoghurt","subject":"Re: [StGit PATCH 2/2] Reuse the same temp index in a transaction","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@gmail.com","sentAt":"2008-07-12T10:24:24Z","receivedAt":"2008-07-12T10:24:24Z","isPatch":true,"sender":{"key":"catalin.marinas@gmail.com","avatar":null},"body":"2008/7/2 Karl Hasselström <kha@treskal.com>:\n> Instead of making a new temp index every time we need one, just keep\n> reusing the same one. And keep track of which tree is currently stored\n> in it -- if we do several consecutive successful pushes, it's always\n> going to be the \"right\" tree so that we don't have to call read-tree\n> before each patch application.\n>\n> The motivation behind this change is of course that it makes things\n> faster.\n>\n> (The same simple test as in the previous patch -- pushing 250 patches\n> in a 32k-file repository, with one file-level merge necessary per push\n> -- went from 0.36 to 0.19 seconds per patch with this patch applied.)\n\nThat's an impressive improvement (together with the previous patch).\nIs this with the new patch log infrastructure?\n\nThanks.\n\n-- \nCatalin\n"},{"id":"83221","messageId":"20080714063551.GD20751@diana.vm.bytemark.co.uk","threadId":"14249","inReplyTo":"b0943d9e0807120324l7674c010w9a8e4a0bbdeeee65@mail.gmail.com","subject":"Re: [StGit PATCH 2/2] Reuse the same temp index in a transaction","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-14T06:35:51Z","receivedAt":"2008-07-14T06:35:51Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2008-07-12 11:24:24 +0100, Catalin Marinas wrote:\n\n> 2008/7/2 Karl Hasselström <kha@treskal.com>:\n>\n> > Instead of making a new temp index every time we need one, just\n> > keep reusing the same one. And keep track of which tree is\n> > currently stored in it -- if we do several consecutive successful\n> > pushes, it's always going to be the \"right\" tree so that we don't\n> > have to call read-tree before each patch application.\n> >\n> > The motivation behind this change is of course that it makes\n> > things faster.\n> >\n> > (The same simple test as in the previous patch -- pushing 250\n> > patches in a 32k-file repository, with one file-level merge\n> > necessary per push -- went from 0.36 to 0.19 seconds per patch\n> > with this patch applied.)\n>\n> That's an impressive improvement (together with the previous patch).\n> Is this with the new patch log infrastructure?\n\nYes, with all the bells and whistles -- in particular, with the\noverhead of the simplified log. (But note that it's a synthetic\nbenchmark, and not a real linux-kernel patch series.)\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"}]}