Skip to content

Commit 42280e9

Browse files
committed
Store fromPos/toPos as 16-bit ints, and reorder fields for better packing
Hopefully, graphs will never get wider than 32768 characters. (They would get kind of hard to navigate if they did...) This reduces the size of the Pipe struct from 48 to 32 bytes, which makes a significant difference when there are many millions of instances.
1 parent 313cfe0 commit 42280e9

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

pkg/gui/presentation/graph/graph.go

+24-21
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,21 @@ const (
2323
)
2424

2525
type Pipe struct {
26-
fromPos int
27-
toPos int
2826
fromHash *string
2927
toHash *string
30-
kind PipeKind
3128
style *style.TextStyle
29+
fromPos int16
30+
toPos int16
31+
kind PipeKind
3232
}
3333

3434
var highlightStyle = style.FgLightWhite.SetBold()
3535

36-
func (self Pipe) left() int {
36+
func (self Pipe) left() int16 {
3737
return min(self.fromPos, self.toPos)
3838
}
3939

40-
func (self Pipe) right() int {
40+
func (self Pipe) right() int16 {
4141
return max(self.fromPos, self.toPos)
4242
}
4343

@@ -103,7 +103,7 @@ func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHash *
103103
}
104104

105105
func getNextPipes(hashPool *utils.StringPool, prevPipes []Pipe, commit *models.Commit, getStyle func(c *models.Commit) *style.TextStyle) []Pipe {
106-
maxPos := 0
106+
maxPos := int16(0)
107107
for _, pipe := range prevPipes {
108108
if pipe.toPos > maxPos {
109109
maxPos = pipe.toPos
@@ -129,6 +129,9 @@ func getNextPipes(hashPool *utils.StringPool, prevPipes []Pipe, commit *models.C
129129
}
130130

131131
// a taken spot is one where a current pipe is ending on
132+
// Note: this set and similar ones below use int instead of int16 because
133+
// that's much more efficient. We cast the int16 values we store in these
134+
// sets to int on every access.
132135
takenSpots := set.New[int]()
133136
// a traversed spot is one where a current pipe is starting on, ending on, or passing through
134137
traversedSpots := set.New[int]()
@@ -156,41 +159,41 @@ func getNextPipes(hashPool *utils.StringPool, prevPipes []Pipe, commit *models.C
156159
traversedSpotsForContinuingPipes := set.New[int]()
157160
for _, pipe := range currentPipes {
158161
if !equalHashes(pipe.toHash, commit.Hash) {
159-
traversedSpotsForContinuingPipes.Add(pipe.toPos)
162+
traversedSpotsForContinuingPipes.Add(int(pipe.toPos))
160163
}
161164
}
162165

163-
getNextAvailablePosForContinuingPipe := func() int {
164-
i := 0
166+
getNextAvailablePosForContinuingPipe := func() int16 {
167+
i := int16(0)
165168
for {
166-
if !traversedSpots.Includes(i) {
169+
if !traversedSpots.Includes(int(i)) {
167170
return i
168171
}
169172
i++
170173
}
171174
}
172175

173-
getNextAvailablePosForNewPipe := func() int {
174-
i := 0
176+
getNextAvailablePosForNewPipe := func() int16 {
177+
i := int16(0)
175178
for {
176179
// a newly created pipe is not allowed to end on a spot that's already taken,
177180
// nor on a spot that's been traversed by a continuing pipe.
178-
if !takenSpots.Includes(i) && !traversedSpotsForContinuingPipes.Includes(i) {
181+
if !takenSpots.Includes(int(i)) && !traversedSpotsForContinuingPipes.Includes(int(i)) {
179182
return i
180183
}
181184
i++
182185
}
183186
}
184187

185-
traverse := func(from, to int) {
188+
traverse := func(from, to int16) {
186189
left, right := from, to
187190
if left > right {
188191
left, right = right, left
189192
}
190193
for i := left; i <= right; i++ {
191-
traversedSpots.Add(i)
194+
traversedSpots.Add(int(i))
192195
}
193-
takenSpots.Add(to)
196+
takenSpots.Add(int(to))
194197
}
195198

196199
for _, pipe := range currentPipes {
@@ -233,7 +236,7 @@ func getNextPipes(hashPool *utils.StringPool, prevPipes []Pipe, commit *models.C
233236
style: getStyle(commit),
234237
})
235238

236-
takenSpots.Add(availablePos)
239+
takenSpots.Add(int(availablePos))
237240
}
238241
}
239242

@@ -242,7 +245,7 @@ func getNextPipes(hashPool *utils.StringPool, prevPipes []Pipe, commit *models.C
242245
// continuing on, potentially moving left to fill in a blank spot
243246
last := pipe.toPos
244247
for i := pipe.toPos; i > pos; i-- {
245-
if takenSpots.Includes(i) || traversedSpots.Includes(i) {
248+
if takenSpots.Includes(int(i)) || traversedSpots.Includes(int(i)) {
246249
break
247250
} else {
248251
last = i
@@ -276,8 +279,8 @@ func renderPipeSet(
276279
selectedCommitHash *string,
277280
prevCommit *models.Commit,
278281
) string {
279-
maxPos := 0
280-
commitPos := 0
282+
maxPos := int16(0)
283+
commitPos := int16(0)
281284
startCount := 0
282285
for _, pipe := range pipes {
283286
if pipe.kind == STARTS {
@@ -293,7 +296,7 @@ func renderPipeSet(
293296
}
294297
isMerge := startCount > 1
295298

296-
cells := lo.Map(lo.Range(maxPos+1), func(i int, _ int) *Cell {
299+
cells := lo.Map(lo.Range(int(maxPos)+1), func(i int, _ int) *Cell {
297300
return &Cell{cellType: CONNECTION, style: &style.FgDefault}
298301
})
299302

0 commit comments

Comments
 (0)