Skip to content

Commit d49a18d

Browse files
committed
Store Pipe objects by value in slice of Pipes
This saves some memory at the cost of a slight performance increase (I suppose reallocting the slice when adding new Pipes is slightly more expensive now). Performance of the BenchmarkRenderCommitGraph benchmark is 130μs before, 175μs after. I'm guessing this is still acceptable.
1 parent 50a200e commit d49a18d

File tree

3 files changed

+43
-43
lines changed

3 files changed

+43
-43
lines changed

pkg/gui/presentation/commits.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type pipeSetCacheKey struct {
2828
}
2929

3030
var (
31-
pipeSetCache = make(map[pipeSetCacheKey][][]*graph.Pipe)
31+
pipeSetCache = make(map[pipeSetCacheKey][][]graph.Pipe)
3232
mutex deadlock.Mutex
3333
)
3434

@@ -245,7 +245,7 @@ func indexOfFirstNonTODOCommit(commits []*models.Commit) int {
245245
return 0
246246
}
247247

248-
func loadPipesets(commits []*models.Commit) [][]*graph.Pipe {
248+
func loadPipesets(commits []*models.Commit) [][]graph.Pipe {
249249
// given that our cache key is a commit hash and a commit count, it's very important that we don't actually try to render pipes
250250
// when dealing with things like filtered commits.
251251
cacheKey := pipeSetCacheKey{

pkg/gui/presentation/graph/graph.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,20 @@ func RenderCommitGraph(commits []*models.Commit, selectedCommitHash *string, get
5656
return lines
5757
}
5858

59-
func GetPipeSets(commits []*models.Commit, getStyle func(c *models.Commit) style.TextStyle) [][]*Pipe {
59+
func GetPipeSets(commits []*models.Commit, getStyle func(c *models.Commit) style.TextStyle) [][]Pipe {
6060
if len(commits) == 0 {
6161
return nil
6262
}
6363

64-
pipes := []*Pipe{{fromPos: 0, toPos: 0, fromHash: &StartCommitHash, toHash: commits[0].HashPtr(), kind: STARTS, style: style.FgDefault}}
64+
pipes := []Pipe{{fromPos: 0, toPos: 0, fromHash: &StartCommitHash, toHash: commits[0].HashPtr(), kind: STARTS, style: style.FgDefault}}
6565

66-
return lo.Map(commits, func(commit *models.Commit, _ int) []*Pipe {
66+
return lo.Map(commits, func(commit *models.Commit, _ int) []Pipe {
6767
pipes = getNextPipes(pipes, commit, getStyle)
6868
return pipes
6969
})
7070
}
7171

72-
func RenderAux(pipeSets [][]*Pipe, commits []*models.Commit, selectedCommitHash *string) []string {
72+
func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHash *string) []string {
7373
maxProcs := runtime.GOMAXPROCS(0)
7474

7575
// splitting up the rendering of the graph into multiple goroutines allows us to render the graph in parallel
@@ -106,7 +106,7 @@ func RenderAux(pipeSets [][]*Pipe, commits []*models.Commit, selectedCommitHash
106106
return lo.Flatten(chunks)
107107
}
108108

109-
func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *models.Commit) style.TextStyle) []*Pipe {
109+
func getNextPipes(prevPipes []Pipe, commit *models.Commit, getStyle func(c *models.Commit) style.TextStyle) []Pipe {
110110
maxPos := 0
111111
for _, pipe := range prevPipes {
112112
if pipe.toPos > maxPos {
@@ -116,11 +116,11 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
116116

117117
// a pipe that terminated in the previous line has no bearing on the current line
118118
// so we'll filter those out
119-
currentPipes := lo.Filter(prevPipes, func(pipe *Pipe, _ int) bool {
119+
currentPipes := lo.Filter(prevPipes, func(pipe Pipe, _ int) bool {
120120
return pipe.kind != TERMINATES
121121
})
122122

123-
newPipes := make([]*Pipe, 0, len(currentPipes)+len(commit.ParentPtrs()))
123+
newPipes := make([]Pipe, 0, len(currentPipes)+len(commit.ParentPtrs()))
124124
// start by assuming that we've got a brand new commit not related to any preceding commit.
125125
// (this only happens when we're doing `git log --all`). These will be tacked onto the far end.
126126
pos := maxPos + 1
@@ -143,7 +143,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
143143
} else {
144144
toHash = commit.ParentPtrs()[0]
145145
}
146-
newPipes = append(newPipes, &Pipe{
146+
newPipes = append(newPipes, Pipe{
147147
fromPos: pos,
148148
toPos: pos,
149149
fromHash: commit.HashPtr(),
@@ -195,7 +195,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
195195
for _, pipe := range currentPipes {
196196
if equalHashes(pipe.toHash, commit.HashPtr()) {
197197
// terminating here
198-
newPipes = append(newPipes, &Pipe{
198+
newPipes = append(newPipes, Pipe{
199199
fromPos: pipe.toPos,
200200
toPos: pos,
201201
fromHash: pipe.fromHash,
@@ -207,7 +207,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
207207
} else if pipe.toPos < pos {
208208
// continuing here
209209
availablePos := getNextAvailablePosForContinuingPipe()
210-
newPipes = append(newPipes, &Pipe{
210+
newPipes = append(newPipes, Pipe{
211211
fromPos: pipe.toPos,
212212
toPos: availablePos,
213213
fromHash: pipe.fromHash,
@@ -223,7 +223,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
223223
for _, parent := range commit.ParentPtrs()[1:] {
224224
availablePos := getNextAvailablePosForNewPipe()
225225
// need to act as if continuing pipes are going to continue on the same line.
226-
newPipes = append(newPipes, &Pipe{
226+
newPipes = append(newPipes, Pipe{
227227
fromPos: pos,
228228
toPos: availablePos,
229229
fromHash: commit.HashPtr(),
@@ -247,7 +247,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
247247
last = i
248248
}
249249
}
250-
newPipes = append(newPipes, &Pipe{
250+
newPipes = append(newPipes, Pipe{
251251
fromPos: pipe.toPos,
252252
toPos: last,
253253
fromHash: pipe.fromHash,
@@ -260,7 +260,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
260260
}
261261

262262
// not efficient but doing it for now: sorting my pipes by toPos, then by kind
263-
slices.SortFunc(newPipes, func(a, b *Pipe) int {
263+
slices.SortFunc(newPipes, func(a, b Pipe) int {
264264
if a.toPos == b.toPos {
265265
return cmp.Compare(a.kind, b.kind)
266266
}
@@ -271,7 +271,7 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod
271271
}
272272

273273
func renderPipeSet(
274-
pipes []*Pipe,
274+
pipes []Pipe,
275275
selectedCommitHash *string,
276276
prevCommit *models.Commit,
277277
) string {
@@ -330,19 +330,19 @@ func renderPipeSet(
330330

331331
// so we have our commit pos again, now it's time to build the cells.
332332
// we'll handle the one that's sourced from our selected commit last so that it can override the other cells.
333-
selectedPipes, nonSelectedPipes := utils.Partition(pipes, func(pipe *Pipe) bool {
333+
selectedPipes, nonSelectedPipes := utils.Partition(pipes, func(pipe Pipe) bool {
334334
return highlight && equalHashes(pipe.fromHash, selectedCommitHash)
335335
})
336336

337337
for _, pipe := range nonSelectedPipes {
338338
if pipe.kind == STARTS {
339-
renderPipe(pipe, pipe.style, true)
339+
renderPipe(&pipe, pipe.style, true)
340340
}
341341
}
342342

343343
for _, pipe := range nonSelectedPipes {
344344
if pipe.kind != STARTS && !(pipe.kind == TERMINATES && pipe.fromPos == commitPos && pipe.toPos == commitPos) {
345-
renderPipe(pipe, pipe.style, false)
345+
renderPipe(&pipe, pipe.style, false)
346346
}
347347
}
348348

@@ -352,7 +352,7 @@ func renderPipeSet(
352352
}
353353
}
354354
for _, pipe := range selectedPipes {
355-
renderPipe(pipe, highlightStyle, true)
355+
renderPipe(&pipe, highlightStyle, true)
356356
if pipe.toPos == commitPos {
357357
cells[pipe.toPos].setStyle(highlightStyle)
358358
}

pkg/gui/presentation/graph/graph_test.go

+23-23
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,15 @@ func TestRenderPipeSet(t *testing.T) {
261261

262262
tests := []struct {
263263
name string
264-
pipes []*Pipe
264+
pipes []Pipe
265265
commit *models.Commit
266266
prevCommit *models.Commit
267267
expectedStr string
268268
expectedStyles []style.TextStyle
269269
}{
270270
{
271271
name: "single cell",
272-
pipes: []*Pipe{
272+
pipes: []Pipe{
273273
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("b"), kind: TERMINATES, style: cyan},
274274
{fromPos: 0, toPos: 0, fromHash: pool("b"), toHash: pool("c"), kind: STARTS, style: green},
275275
},
@@ -279,7 +279,7 @@ func TestRenderPipeSet(t *testing.T) {
279279
},
280280
{
281281
name: "single cell, selected",
282-
pipes: []*Pipe{
282+
pipes: []Pipe{
283283
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("selected"), kind: TERMINATES, style: cyan},
284284
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("c"), kind: STARTS, style: green},
285285
},
@@ -289,7 +289,7 @@ func TestRenderPipeSet(t *testing.T) {
289289
},
290290
{
291291
name: "terminating hook and starting hook, selected",
292-
pipes: []*Pipe{
292+
pipes: []Pipe{
293293
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("selected"), kind: TERMINATES, style: cyan},
294294
{fromPos: 1, toPos: 0, fromHash: pool("c"), toHash: pool("selected"), kind: TERMINATES, style: yellow},
295295
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("d"), kind: STARTS, style: green},
@@ -303,7 +303,7 @@ func TestRenderPipeSet(t *testing.T) {
303303
},
304304
{
305305
name: "terminating hook and starting hook, prioritise the terminating one",
306-
pipes: []*Pipe{
306+
pipes: []Pipe{
307307
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("b"), kind: TERMINATES, style: red},
308308
{fromPos: 1, toPos: 0, fromHash: pool("c"), toHash: pool("b"), kind: TERMINATES, style: magenta},
309309
{fromPos: 0, toPos: 0, fromHash: pool("b"), toHash: pool("d"), kind: STARTS, style: green},
@@ -317,7 +317,7 @@ func TestRenderPipeSet(t *testing.T) {
317317
},
318318
{
319319
name: "starting and terminating pipe sharing some space",
320-
pipes: []*Pipe{
320+
pipes: []Pipe{
321321
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
322322
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
323323
{fromPos: 1, toPos: 1, fromHash: pool("b1"), toHash: pool("b2"), kind: CONTINUES, style: magenta},
@@ -332,7 +332,7 @@ func TestRenderPipeSet(t *testing.T) {
332332
},
333333
{
334334
name: "starting and terminating pipe sharing some space, with selection",
335-
pipes: []*Pipe{
335+
pipes: []Pipe{
336336
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("selected"), kind: TERMINATES, style: red},
337337
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("a3"), kind: STARTS, style: yellow},
338338
{fromPos: 1, toPos: 1, fromHash: pool("b1"), toHash: pool("b2"), kind: CONTINUES, style: magenta},
@@ -347,7 +347,7 @@ func TestRenderPipeSet(t *testing.T) {
347347
},
348348
{
349349
name: "many terminating pipes",
350-
pipes: []*Pipe{
350+
pipes: []Pipe{
351351
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
352352
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
353353
{fromPos: 1, toPos: 0, fromHash: pool("b1"), toHash: pool("a2"), kind: TERMINATES, style: magenta},
@@ -361,7 +361,7 @@ func TestRenderPipeSet(t *testing.T) {
361361
},
362362
{
363363
name: "starting pipe passing through",
364-
pipes: []*Pipe{
364+
pipes: []Pipe{
365365
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
366366
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
367367
{fromPos: 0, toPos: 3, fromHash: pool("a2"), toHash: pool("d3"), kind: STARTS, style: yellow},
@@ -376,7 +376,7 @@ func TestRenderPipeSet(t *testing.T) {
376376
},
377377
{
378378
name: "starting and terminating path crossing continuing path",
379-
pipes: []*Pipe{
379+
pipes: []Pipe{
380380
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
381381
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
382382
{fromPos: 0, toPos: 1, fromHash: pool("a2"), toHash: pool("b3"), kind: STARTS, style: yellow},
@@ -391,7 +391,7 @@ func TestRenderPipeSet(t *testing.T) {
391391
},
392392
{
393393
name: "another clash of starting and terminating paths",
394-
pipes: []*Pipe{
394+
pipes: []Pipe{
395395
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
396396
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
397397
{fromPos: 0, toPos: 1, fromHash: pool("a2"), toHash: pool("b3"), kind: STARTS, style: yellow},
@@ -406,7 +406,7 @@ func TestRenderPipeSet(t *testing.T) {
406406
},
407407
{
408408
name: "commit whose previous commit is selected",
409-
pipes: []*Pipe{
409+
pipes: []Pipe{
410410
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("a2"), kind: TERMINATES, style: red},
411411
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: yellow},
412412
},
@@ -418,7 +418,7 @@ func TestRenderPipeSet(t *testing.T) {
418418
},
419419
{
420420
name: "commit whose previous commit is selected and is a merge commit",
421-
pipes: []*Pipe{
421+
pipes: []Pipe{
422422
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("a2"), kind: TERMINATES, style: red},
423423
{fromPos: 1, toPos: 1, fromHash: pool("selected"), toHash: pool("b3"), kind: CONTINUES, style: red},
424424
},
@@ -430,7 +430,7 @@ func TestRenderPipeSet(t *testing.T) {
430430
},
431431
{
432432
name: "commit whose previous commit is selected and is a merge commit, with continuing pipe inbetween",
433-
pipes: []*Pipe{
433+
pipes: []Pipe{
434434
{fromPos: 0, toPos: 0, fromHash: pool("selected"), toHash: pool("a2"), kind: TERMINATES, style: red},
435435
{fromPos: 1, toPos: 1, fromHash: pool("z1"), toHash: pool("z3"), kind: CONTINUES, style: green},
436436
{fromPos: 2, toPos: 2, fromHash: pool("selected"), toHash: pool("b3"), kind: CONTINUES, style: red},
@@ -443,7 +443,7 @@ func TestRenderPipeSet(t *testing.T) {
443443
},
444444
{
445445
name: "when previous commit is selected, not a merge commit, and spawns a continuing pipe",
446-
pipes: []*Pipe{
446+
pipes: []Pipe{
447447
{fromPos: 0, toPos: 0, fromHash: pool("a1"), toHash: pool("a2"), kind: TERMINATES, style: red},
448448
{fromPos: 0, toPos: 0, fromHash: pool("a2"), toHash: pool("a3"), kind: STARTS, style: green},
449449
{fromPos: 0, toPos: 1, fromHash: pool("a2"), toHash: pool("b3"), kind: STARTS, style: green},
@@ -486,25 +486,25 @@ func TestGetNextPipes(t *testing.T) {
486486
pool := func(s string) *string { return hashPool.Add(s) }
487487

488488
tests := []struct {
489-
prevPipes []*Pipe
489+
prevPipes []Pipe
490490
commit *models.Commit
491-
expected []*Pipe
491+
expected []Pipe
492492
}{
493493
{
494-
prevPipes: []*Pipe{
494+
prevPipes: []Pipe{
495495
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("b"), kind: STARTS, style: style.FgDefault},
496496
},
497497
commit: models.NewCommit(hashPool, models.NewCommitOpts{
498498
Hash: "b",
499499
Parents: []string{"c"},
500500
}),
501-
expected: []*Pipe{
501+
expected: []Pipe{
502502
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("b"), kind: TERMINATES, style: style.FgDefault},
503503
{fromPos: 0, toPos: 0, fromHash: pool("b"), toHash: pool("c"), kind: STARTS, style: style.FgDefault},
504504
},
505505
},
506506
{
507-
prevPipes: []*Pipe{
507+
prevPipes: []Pipe{
508508
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("b"), kind: TERMINATES, style: style.FgDefault},
509509
{fromPos: 0, toPos: 0, fromHash: pool("b"), toHash: pool("c"), kind: STARTS, style: style.FgDefault},
510510
{fromPos: 0, toPos: 1, fromHash: pool("b"), toHash: pool("d"), kind: STARTS, style: style.FgDefault},
@@ -513,21 +513,21 @@ func TestGetNextPipes(t *testing.T) {
513513
Hash: "d",
514514
Parents: []string{"e"},
515515
}),
516-
expected: []*Pipe{
516+
expected: []Pipe{
517517
{fromPos: 0, toPos: 0, fromHash: pool("b"), toHash: pool("c"), kind: CONTINUES, style: style.FgDefault},
518518
{fromPos: 1, toPos: 1, fromHash: pool("b"), toHash: pool("d"), kind: TERMINATES, style: style.FgDefault},
519519
{fromPos: 1, toPos: 1, fromHash: pool("d"), toHash: pool("e"), kind: STARTS, style: style.FgDefault},
520520
},
521521
},
522522
{
523-
prevPipes: []*Pipe{
523+
prevPipes: []Pipe{
524524
{fromPos: 0, toPos: 0, fromHash: pool("a"), toHash: pool("root"), kind: TERMINATES, style: style.FgDefault},
525525
},
526526
commit: models.NewCommit(hashPool, models.NewCommitOpts{
527527
Hash: "root",
528528
Parents: []string{},
529529
}),
530-
expected: []*Pipe{
530+
expected: []Pipe{
531531
{fromPos: 1, toPos: 1, fromHash: pool("root"), toHash: pool(models.EmptyTreeCommitHash), kind: STARTS, style: style.FgDefault},
532532
},
533533
},

0 commit comments

Comments
 (0)