Skip to content

Commit 0a65126

Browse files
authored
Merge pull request #231 from twitchdev/fix-229
Fix #229
2 parents 128f0ca + e748f82 commit 0a65126

File tree

4 files changed

+68
-7
lines changed

4 files changed

+68
-7
lines changed

.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ twitch-cli
2626
# SSL certs for HTTPS/WSS
2727
*.crt
2828
*.csr
29-
*.key
29+
*.key
30+
31+
# Go profiler
32+
*.prof
33+
*.prof.gz

CONTRIBUTING.md

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Thanks for helping make the Twitch CLI better!
66
- [Report an Issue](#report-an-issue)
77
- [Contributing Code with Pull Requests](#contributing-code-with-pull-requests)
88
- [Requirements](#requirements)
9+
- [Profiling](#profiling)
910
- [Code of Conduct](#code-of-conduct)
1011
- [Licensing](#licensing)
1112

@@ -47,6 +48,11 @@ As noted in the [README](./README.md), all commands follow the following structu
4748

4849
Some commands may not be part of a designated product (for example, the `token` and `version` commands) - if you are building functionality that is not tied to a Twitch product, please open the PR to discuss further.
4950

51+
### Profiling
52+
53+
The Twitch CLI makes use of [pprof](https://github.com/google/pprof) for CPU profiling. This can be enabled on any system by setting the environment variable `TWITCH_CLI_ENABLE_CPU_PROFILER` to `true`.
54+
By default, the CPU profile will be written to your system as `cpu.prof` when the program exits. This filename can be modified with the environment variable `TWITCH_CLI_CPU_PROFILER_FILE`.
55+
5056
## Code of Conduct
5157

5258
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).

internal/events/websocket/mock_server/server.go

+19-6
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,21 @@ func (ws *WebSocketServer) WsPageHandler(w http.ResponseWriter, r *http.Request)
161161
client.pingLoopChan = make(chan struct{})
162162
client.keepAliveChanOpen = true
163163
client.pingChanOpen = true
164-
go func() {
165-
// Set pong handler. Resets the read deadline when pong is received.
166-
conn.SetPongHandler(func(string) error {
167-
conn.SetReadDeadline(time.Now().Add(time.Second * KEEPALIVE_TIMEOUT_SECONDS))
168-
return nil
169-
})
170164

165+
// Set pong handler. Resets the read deadline when pong is received.
166+
conn.SetPongHandler(func(string) error {
167+
conn.SetReadDeadline(time.Now().Add(time.Second * KEEPALIVE_TIMEOUT_SECONDS))
168+
return nil
169+
})
170+
171+
// Keep Alive message loop
172+
go func() {
171173
for {
172174
select {
173175
case <-client.keepAliveLoopChan:
174176
client.keepAliveTimer.Stop()
177+
client.keepAliveLoopChan = nil
178+
return
175179

176180
case <-client.keepAliveTimer.C: // Send KeepAlive message
177181
keepAliveMsg, _ := json.Marshal(
@@ -192,9 +196,18 @@ func (ws *WebSocketServer) WsPageHandler(w http.ResponseWriter, r *http.Request)
192196
if ws.DebugEnabled {
193197
log.Printf("Sent session_keepalive to client [%s]", client.clientName)
194198
}
199+
}
200+
}
201+
}()
195202

203+
// Ping/pong handler loop
204+
go func() {
205+
for {
206+
select {
196207
case <-client.pingLoopChan:
197208
client.pingTimer.Stop()
209+
client.pingLoopChan = nil
210+
return
198211

199212
case <-client.pingTimer.C: // Send ping
200213
err := client.SendMessage(websocket.PingMessage, []byte{})

main.go

+38
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,51 @@
33
package main
44

55
import (
6+
"log"
7+
"os"
8+
"runtime/pprof"
9+
"strconv"
10+
"strings"
11+
612
"github.com/twitchdev/twitch-cli/cmd"
713
"github.com/twitchdev/twitch-cli/internal/util"
814
)
915

1016
var buildVersion string
1117

18+
const (
19+
CPU_PROFILER_BOOL_ENV_VARIABLE = "TWITCH_CLI_ENABLE_CPU_PROFILER"
20+
CPU_PROFILER_FILENAME_ENV_VARIABLE = "TWITCH_CLI_CPU_PROFILER_FILE"
21+
CPU_PROFILER_DEFAULT_FILENAME = "cpu.prof"
22+
)
23+
1224
func main() {
25+
enableCpuProfiler, err := strconv.ParseBool(os.Getenv(CPU_PROFILER_BOOL_ENV_VARIABLE))
26+
if err != nil {
27+
enableCpuProfiler = false
28+
}
29+
30+
// Enable CPU profiler
31+
if enableCpuProfiler {
32+
cpuProfilerFilename := os.Getenv(CPU_PROFILER_FILENAME_ENV_VARIABLE)
33+
if strings.TrimSpace(cpuProfilerFilename) == "" {
34+
cpuProfilerFilename = CPU_PROFILER_DEFAULT_FILENAME
35+
}
36+
37+
f, err := os.Create(cpuProfilerFilename)
38+
if err != nil {
39+
log.Fatal("Could not create CPU profile: ", err)
40+
}
41+
defer f.Close()
42+
43+
err = pprof.StartCPUProfile(f)
44+
if err != nil {
45+
log.Fatal("Could not start CPU profile: ", err)
46+
}
47+
48+
defer pprof.StopCPUProfile()
49+
}
50+
1351
if len(buildVersion) > 0 {
1452
util.SetVersion(buildVersion)
1553
}

0 commit comments

Comments
 (0)