-
Notifications
You must be signed in to change notification settings - Fork 0
/
persistence_profiler.go
111 lines (96 loc) · 2.26 KB
/
persistence_profiler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import (
"fmt"
"log"
"os"
"sync"
"time"
)
type PersistenceProfiler struct {
p *Persistence
csvFile *os.File
csvFileLock sync.Mutex
}
func NewPersistenceProfiler(p *Persistence) (*PersistenceProfiler, error) {
csvFile, err := os.Create("output/perf-" + fmt.Sprint(time.Now().Unix()) + ".csv")
if err != nil {
return nil, err
}
return &PersistenceProfiler{
p: p,
csvFile: csvFile,
}, nil
}
func (pp *PersistenceProfiler) Cleanup() {
pp.csvFile.Close()
}
func (pp *PersistenceProfiler) Perform() error {
// log concurrent reading and writing
wg := sync.WaitGroup{}
errCh := make(chan error)
go func() {
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
time.Sleep(time.Duration(10) * time.Millisecond)
defer wg.Done()
if _, err := pp.queryUnseenMessages(); err != nil {
errCh <- fmt.Errorf("queryUnseenMessages failed: %v", err)
}
}()
}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
time.Sleep(time.Duration(1) * time.Millisecond)
defer wg.Done()
if err := pp.insertUnseenMessage(); err != nil {
errCh <- fmt.Errorf("insertUnseenMessage failed: %v", err)
}
}()
}
wg.Wait()
close(errCh)
}()
for err := range errCh {
if err != nil {
return err // return on first error
}
}
return nil
}
func (pp *PersistenceProfiler) queryUnseenMessages() ([]string, error) {
logger := PerfLogger{
csvFile: pp.csvFile,
csvFileLock: &pp.csvFileLock,
apiName: "QueryUnseenMessages",
start: time.Now(),
}
defer logger.Complete()
return pp.p.QueryUnseenMessages()
}
func (pp *PersistenceProfiler) insertUnseenMessage() error {
logger := PerfLogger{
csvFile: pp.csvFile,
csvFileLock: &pp.csvFileLock,
apiName: "InsertUnseenMessage",
start: time.Now(),
}
defer logger.Complete()
return pp.p.InsertUnseenMessage()
}
type PerfLogger struct {
csvFile *os.File
csvFileLock *sync.Mutex
apiName string
start time.Time
}
func (pf *PerfLogger) Complete() {
duration := time.Since(pf.start)
line := fmt.Sprintf("%sµ%d\n", pf.apiName, duration.Nanoseconds())
pf.csvFileLock.Lock()
defer pf.csvFileLock.Unlock()
if _, err := pf.csvFile.Write([]byte(line)); err != nil {
log.Println("could not write to csv", err)
}
}