aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Symonds <dsymonds@golang.org>2019-11-21 09:51:39 +1100
committerDavid Symonds <dsymonds@golang.org>2020-03-10 09:57:31 +1100
commitd3dd84b7108ed4a062dced6e1d2d5dd4537c9e57 (patch)
tree53c87602397a3aef815393294c9322e080d13a51
parent18a858b38ca4197987a6da7058ab0397255fa82c (diff)
downloadgo-git-d3dd84b7108ed4a062dced6e1d2d5dd4537c9e57.tar.gz
plumbing/object: avoid O(N^2) string building when decoding commit message
Most commits have relatively small messages, so this was never noticeable. However, there are some repositories that have semi-automated messages that can get very large (e.g. github.com/riscv/riscv-clang and its riscv-trunk branch), on the order of 109k lines. Changing from string += to using a bytes.Buffer reduces the time for Commit.Decode for that specific case from 35s to 74ms. Signed-off-by: David Symonds <dsymonds@golang.org>
-rw-r--r--plumbing/object/commit.go7
1 files changed, 5 insertions, 2 deletions
diff --git a/plumbing/object/commit.go b/plumbing/object/commit.go
index 6b50934..eb86a01 100644
--- a/plumbing/object/commit.go
+++ b/plumbing/object/commit.go
@@ -177,6 +177,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
var message bool
var pgpsig bool
+ var msgbuf bytes.Buffer
for {
line, err := r.ReadBytes('\n')
if err != nil && err != io.EOF {
@@ -221,13 +222,15 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
pgpsig = true
}
} else {
- c.Message += string(line)
+ msgbuf.Write(line)
}
if err == io.EOF {
- return nil
+ break
}
}
+ c.Message = msgbuf.String()
+ return nil
}
// Encode transforms a Commit into a plumbing.EncodedObject.