Skip to content

Commit 459be4f

Browse files
committed
Fix frame invalidation
1 parent 4ea587f commit 459be4f

5 files changed

Lines changed: 24 additions & 38 deletions

File tree

cmd/subcommands/acci-ping/acci-ping.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ type Config struct {
2727
*application.SharedFlags
2828
*tabflags.FlagSet
2929

30-
debugFps *int
3130
debuggingTermSize *string
3231
filePath *string
3332
followingOnStart *bool
@@ -69,7 +68,6 @@ func GetFlags(info *application.BuildInfo) *Config {
6968
debuggingTermSize: tf.String("debug-term-size", "", "switches the terminal to fixed mode and no iteractivity",
7069
tabflags.AutoComplete{Choices: []string{"15x80", "20x85", "HxW"}}),
7170
followingOnStart: tf.Bool("follow", false, "if this flag is used the graph will be shown in following mode immediately"),
72-
debugFps: tf.Int("debug-fps", 240, "configures the internal tickrate for the graph re-paint look (in FPS)"),
7371
logarithmicOnStart: tf.Bool("logarithmic", false, "if this flag is used the graph will be shown in logarithmic mode immediately"),
7472
}
7573
*ret.pingBufferingLimit = 10

cmd/subcommands/acci-ping/application.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func (app *Application) Run(
108108
defer close(guiControlChannel)
109109
defer close(guiSpeedChange)
110110
// Very high FPS is good for responsiveness in the UI (since it's locked) and re-drawing on a re-size.
111-
graph, cleanup, terminalSizeUpdates, err := app.g.Run(ctx, cancelFunc, *app.config.debugFps, app.listeners(), app.fallbacks)
111+
graph, cleanup, terminalSizeUpdates, err := app.g.Run(ctx, cancelFunc, app.listeners(), app.fallbacks)
112112
termRecover := func() {
113113
_ = app.term.ClearScreen(terminal.UpdateSize)
114114
cleanup()

graph/drawing.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ import (
2828
)
2929

3030
type computeFrameConfig struct {
31-
timeBetweenFrames time.Duration
32-
followLatestSpan bool
33-
drawSpinner bool
34-
yAxisScale YAxisScale
31+
followLatestSpan bool
32+
drawSpinner bool
33+
yAxisScale YAxisScale
3534
}
3635

3736
func (c computeFrameConfig) Match(cfg computeFrameConfig) bool {
@@ -41,14 +40,6 @@ func (c computeFrameConfig) Match(cfg computeFrameConfig) bool {
4140

4241
const drawingDebug = false
4342

44-
func getTimeBetweenFrames(fps int, pingsPerMinute ping.PingsPerMinute) time.Duration {
45-
if fps == 0 {
46-
return ping.PingsPerMinuteToDuration(pingsPerMinute)
47-
} else {
48-
return time.Duration(1000/fps) * time.Millisecond
49-
}
50-
}
51-
5243
var noFrame = func(w io.Writer) error { return nil }
5344

5445
func (g *Graph) computeFrame(cfg computeFrameConfig) func(io.Writer) error {

graph/graph.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ import (
2525
)
2626

2727
type Graph struct {
28-
ui gui.GUI
29-
Term *terminal.Terminal
30-
dataChannel <-chan ping.PingResults
31-
data *graphdata.GraphData
32-
frameMutex *sync.Mutex
33-
drawingBuffer *draw.Buffer
34-
presentation *controlState
28+
ui gui.GUI
29+
Term *terminal.Terminal
30+
dataChannel <-chan ping.PingResults
31+
data *graphdata.GraphData
32+
frameMutex *sync.Mutex
33+
drawingBuffer *draw.Buffer
34+
presentation *controlState
35+
3536
controlChannel <-chan Control
3637
lastFrame frame
3738
initial ping.PingsPerMinute
@@ -128,12 +129,9 @@ func NewGraph(ctx context.Context, cfg GraphConfiguration) *Graph {
128129
func (g *Graph) Run(
129130
ctx context.Context,
130131
stop context.CancelCauseFunc,
131-
fps int, // this isn't really an FPS given how the GUI is setup and paint buffers, more like a max re-paint delay timer thing.
132132
listeners []terminal.ConditionalListener,
133133
fallbacks []terminal.Listener,
134134
) (func() error, func(), <-chan terminal.Size, error) {
135-
timeBetweenFrames := getTimeBetweenFrames(fps, g.initial)
136-
frameRate := time.NewTicker(timeBetweenFrames)
137135
cleanup, err := g.Term.StartRaw(ctx, stop, listeners, fallbacks)
138136
if err != nil {
139137
return nil, cleanup, nil, err
@@ -143,12 +141,14 @@ func (g *Graph) Run(
143141
size := g.Term.GetSize()
144142
defer close(terminalUpdates)
145143
slog.Info("running acci-ping")
144+
// The main loop of acci-ping, await on the context (will be fired by the terminal)
146145
for {
147146
select {
148147
case <-ctx.Done():
149148
return context.Cause(ctx)
150-
case <-frameRate.C:
151-
err = g.Term.UpdateSize()
149+
default:
150+
// The main body of acci-ping, get the terminal size and send on the channel if changed
151+
err := g.Term.UpdateSize()
152152
if err != nil {
153153
return err
154154
}
@@ -157,14 +157,18 @@ func (g *Graph) Run(
157157
terminalUpdates <- size
158158
size = g.Term.GetSize()
159159
}
160+
// Lock the presentation layer (this ensures we don't get GUI tearing - as in one component
161+
// has data from last frame and another component has data from this frame), compute a new
162+
// frame. Note that the optimisations to do no drawing are all in this function.
160163
g.presentation.m.Lock()
161164
toWrite := g.computeFrame(computeFrameConfig{
162-
timeBetweenFrames: timeBetweenFrames,
163-
followLatestSpan: g.presentation.Following,
164-
drawSpinner: true,
165-
yAxisScale: g.presentation.YAxisScale,
165+
followLatestSpan: g.presentation.Following,
166+
drawSpinner: true,
167+
yAxisScale: g.presentation.YAxisScale,
166168
})
167169
g.presentation.m.Unlock()
170+
// Now that we have a frame to draw (may just be a spinner update), execute this function
171+
// writing the painted frame to the terminal.
168172
err = toWrite(g.Term)
169173
if err != nil {
170174
return err

graph/graphdata/graphdata.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package graphdata
88

99
import (
1010
"fmt"
11-
"io"
1211
"sync"
1312
"time"
1413

@@ -67,12 +66,6 @@ func (gd *GraphData) Summary() string {
6766
return gd.data.Summary()
6867
}
6968

70-
func (gd *GraphData) AsCompact(w io.Writer) error {
71-
gd.m.Lock()
72-
defer gd.m.Unlock()
73-
return gd.data.AsCompact(w)
74-
}
75-
7669
func (gd *GraphData) Lock() {
7770
gd.m.Lock()
7871
}

0 commit comments

Comments
 (0)