Skip to content

Commit d3dd84b

Browse files
committed
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 <[email protected]>
1 parent 18a858b commit d3dd84b

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

Diff for: plumbing/object/commit.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
177177

178178
var message bool
179179
var pgpsig bool
180+
var msgbuf bytes.Buffer
180181
for {
181182
line, err := r.ReadBytes('\n')
182183
if err != nil && err != io.EOF {
@@ -221,13 +222,15 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
221222
pgpsig = true
222223
}
223224
} else {
224-
c.Message += string(line)
225+
msgbuf.Write(line)
225226
}
226227

227228
if err == io.EOF {
228-
return nil
229+
break
229230
}
230231
}
232+
c.Message = msgbuf.String()
233+
return nil
231234
}
232235

233236
// Encode transforms a Commit into a plumbing.EncodedObject.

0 commit comments

Comments
 (0)