Skip to content

Commit 78f077b

Browse files
committed
feat: add integration tests for statistics and fix inconsistencies in CLI tools
1 parent 1ea2b4c commit 78f077b

File tree

21 files changed

+793
-541
lines changed

21 files changed

+793
-541
lines changed

README.md

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ With Olric, you can instantly create a fast, scalable, shared pool of RAM across
88

99
See [Docker](#docker) and [Sample Code](#sample-code) sections to get started!
1010

11+
Current production version is [v0.3.7](https://github.com/buraksezer/olric/tree/7e13bd0c669b83f2b1ef1716ec8564b2e0098977)
12+
1113
## At a glance
1214

1315
* Designed to share some transient, approximate, fast-changing data between servers,
@@ -45,7 +47,7 @@ failure detection and simple anti-entropy services. So it can be used as an ordi
4547
* [olricd](#olricd)
4648
* [olric-cli](#olric-cli)
4749
* [olric-stats](#olric-stats)
48-
* [olric-load](#olric-load)
50+
* [olric-benchmark](#olric-benchmark)
4951
* [Usage](#usage)
5052
* [Distributed Map](#distributed-map)
5153
* [Put](#put)
@@ -167,7 +169,7 @@ Then, install olricd and its siblings:
167169
go install -v ./cmd/*
168170
```
169171

170-
Now you should access **olricd**, **olric-stats**, **olric-cli** and **olric-load** on your path. You can just run olricd
172+
Now you should access **olricd**, **olric-stats**, **olric-cli** and **olric-benchmark** on your path. You can just run olricd
171173
to start experimenting:
172174

173175
```
@@ -249,7 +251,7 @@ Get a shell to the running container:
249251
kubectl exec -it olric-debug -- /bin/sh
250252
```
251253

252-
Now you have a running Alpine Linux setup on Kubernetes. It includes `olric-cli`, `olric-load` and `olric-stats` commands.
254+
Now you have a running Alpine Linux setup on Kubernetes. It includes `olric-cli`, `olric-benchmark` and `olric-stats` commands.
253255

254256
```bash
255257
/go/src/github.com/buraksezer/olric # olric-cli -a olricd.default.svc.cluster.local:3320
@@ -366,8 +368,11 @@ In order to get more details about the options, call `olric-cli -h` in your shel
366368

367369
### olric-stats
368370

369-
olric-stats calls `Stats` command on a cluster member and prints the result. The returned data from the member includes the Go runtime
370-
metrics and statistics from hosted primary and backup partitions.
371+
olric-stats calls `Stats` command on a given cluster member and prints the result.
372+
The results from the member also includes the Go runtime metrics and statistics from
373+
hosted primary and backup partitions.
374+
375+
You should know that all the statistics are belonged to the current member.
371376

372377
In order to install `olric-stats`:
373378

@@ -378,39 +383,39 @@ go get -u github.com/buraksezer/olric/cmd/olric-stats
378383
Statistics about a partition:
379384

380385
```
381-
olric-stats -p 69
386+
olric-stats --partitions --id 69
382387
PartID: 69
383388
Owner: olric.node:3320
384389
Previous Owners: not found
385390
Backups: not found
386391
DMap count: 1
387392
DMaps:
388-
Name: olric-load-test
393+
Name: olric-benchmark-test
389394
Length: 1374
390395
Allocated: 1048576
391396
Inuse: 47946
392397
Garbage: 0
393398
```
394399

395-
In order to get detailed statistics about the Go runtime, you should call `olric-stats -a <ADDRESS> -r`.
396-
397-
Without giving a partition number, it will print everything about the cluster and hosted primary/backup partitions.
400+
In order to get detailed statistics about the Go runtime, you should call `olric-stats -a <ADDRESS> -r`.
398401
In order to get more details about the command, call `olric-stats -h`.
399402

400-
### olric-load
403+
See [stats/stats.go](stats/stats.go) file to get detailed information about the statistics.
404+
405+
### olric-benchmark
401406

402-
olric-load simulates running commands done by N clients at the same time sending M total queries. It measures response time.
407+
olric-benchmark simulates running commands done by N clients at the same time sending M total queries. It measures response time.
403408

404-
In order to install `olric-load`:
409+
In order to install `olric-benchmark`:
405410

406411
```bash
407-
go get -u github.com/buraksezer/olric/cmd/olric-load
412+
go get -u github.com/buraksezer/olric/cmd/olric-benchmark
408413
```
409414

410415
The following command calls `Put` command for 1M keys on `127.0.0.1:3320` (it's default) and uses `msgpack` for serialization.
411416

412417
```
413-
olric-load -a 192.168.1.3:3320 -s msgpack -k 1000000 -c put
418+
olric-benchmark -a 192.168.1.3:3320 -s msgpack -r 1000000 -T put
414419
### STATS FOR COMMAND: PUT ###
415420
Serializer is msgpack
416421
1000000 requests completed in 6.943316278s
@@ -431,7 +436,7 @@ Serializer is msgpack
431436
144023.397460 requests per second
432437
```
433438

434-
In order to get more details about the command, call `olric-load -h`.
439+
In order to get more details about the command, call `olric-benchmark -h`.
435440

436441
## Usage
437442

client/client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (c *Client) request(req protocol.EncodeDecoder) (protocol.EncodeDecoder, er
129129
}
130130

131131
// Stats exposes some useful metrics to monitor an Olric node.
132-
func (c *Client) Stats(addr string, options ...statsOption) (stats.Stats, error) {
132+
func (c *Client) Stats(addr string, options ...StatsOption) (stats.Stats, error) {
133133
var extra protocol.StatsExtra
134134
for _, opt := range options {
135135
opt(&extra)
@@ -154,9 +154,9 @@ func (c *Client) Stats(addr string, options ...statsOption) (stats.Stats, error)
154154
return s, nil
155155
}
156156

157-
type statsOption func(*protocol.StatsExtra)
157+
type StatsOption func(*protocol.StatsExtra)
158158

159-
func CollectRuntime() statsOption {
159+
func CollectRuntime() StatsOption {
160160
return func(extra *protocol.StatsExtra) {
161161
extra.CollectRuntime = true
162162
}

cmd/olric-load/loader/loader.go renamed to cmd/olric-benchmark/benchmark/benchmark.go

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
package loader
15+
package benchmark
1616

1717
import (
1818
"fmt"
@@ -28,29 +28,32 @@ import (
2828
_serializer "github.com/buraksezer/olric/serializer"
2929
)
3030

31-
type Loader struct {
31+
type Benchmark struct {
3232
mu sync.RWMutex
3333
responses []time.Duration
34-
commands []string
35-
numRequests int
36-
numClients int
34+
requests int
35+
connections int
3736
serializer string
3837
client *client.Client
3938
log *log.Logger
4039
wg sync.WaitGroup
4140
}
4241

43-
func New(addrs, timeout, serializer string,
44-
numClients, keyCount int, logger *log.Logger) (*Loader, error) {
42+
func New(address,
43+
timeout,
44+
serializer string,
45+
conns, requests int,
46+
logger *log.Logger) (*Benchmark, error) {
4547
// Default serializer is Gob serializer, just set nil or use gob keyword to use it.
4648
var s _serializer.Serializer
47-
if serializer == "json" {
49+
switch {
50+
case serializer == "json":
4851
s = _serializer.NewJSONSerializer()
49-
} else if serializer == "msgpack" {
52+
case serializer == "msgpack":
5053
s = _serializer.NewMsgpackSerializer()
51-
} else if serializer == "gob" {
54+
case serializer == "gob":
5255
s = _serializer.NewGobSerializer()
53-
} else {
56+
default:
5457
return nil, fmt.Errorf("invalid serializer: %s", serializer)
5558
}
5659

@@ -59,44 +62,45 @@ func New(addrs, timeout, serializer string,
5962
return nil, err
6063
}
6164
cc := &client.Config{
62-
Servers: strings.Split(addrs, ","),
65+
Servers: strings.Split(address, ","),
6366
Serializer: s,
6467
Client: &config.Client{
6568
DialTimeout: dt,
66-
MaxConn: numClients,
69+
MaxConn: conns,
6770
},
6871
}
72+
6973
c, err := client.New(cc)
7074
if err != nil {
7175
return nil, err
7276
}
73-
l := &Loader{
77+
78+
return &Benchmark{
7479
responses: []time.Duration{},
75-
numRequests: keyCount,
76-
numClients: numClients,
80+
requests: requests,
81+
connections: conns,
7782
client: c,
7883
serializer: serializer,
7984
log: logger,
80-
}
81-
return l, nil
85+
}, nil
8286
}
8387

84-
func (l *Loader) stats(cmd string, elapsed time.Duration) {
85-
l.mu.RLock()
86-
defer l.mu.RUnlock()
88+
func (b *Benchmark) stats(cmd string, elapsed time.Duration) {
89+
b.mu.RLock()
90+
defer b.mu.RUnlock()
8791

88-
l.log.Printf("### STATS FOR COMMAND: %s ###", strings.ToUpper(cmd))
89-
l.log.Printf("Serializer is %s", l.serializer)
90-
l.log.Printf("%d requests completed in %v", l.numRequests, elapsed)
91-
l.log.Printf("%d parallel clients", l.numClients)
92-
l.log.Printf("\n")
92+
b.log.Printf("### STATS FOR COMMAND: %s ###", strings.ToUpper(cmd))
93+
b.log.Printf("Serializer is %s", b.serializer)
94+
b.log.Printf("%d requests completed in %v", b.requests, elapsed)
95+
b.log.Printf("%d parallel clients", b.connections)
96+
b.log.Printf("\n")
9397

9498
var limit time.Duration
9599
var lastper float64
96100
for {
97101
limit += time.Millisecond
98102
var hits, count int
99-
for _, rtime := range l.responses {
103+
for _, rtime := range b.responses {
100104
if rtime < limit {
101105
hits++
102106
}
@@ -112,51 +116,51 @@ func (l *Loader) stats(cmd string, elapsed time.Duration) {
112116
break
113117
}
114118
}
115-
rps := float64(l.numRequests) / (float64(elapsed) / float64(time.Second))
116-
l.log.Printf("\n%f requests per second\n", rps)
119+
rps := float64(b.requests) / (float64(elapsed) / float64(time.Second))
120+
b.log.Printf("\n%f requests per second\n", rps)
117121
}
118122

119-
func (l *Loader) worker(cmd string, ch chan int) {
120-
defer l.wg.Done()
123+
func (b *Benchmark) worker(cmd string, ch chan int) {
124+
defer b.wg.Done()
121125

122-
dm := l.client.NewDMap("olric-load-test")
126+
dm := b.client.NewDMap("olric-benchmark-test")
123127
for i := range ch {
124128
now := time.Now()
125129
switch {
126130
case strings.ToLower(cmd) == "put":
127131
if err := dm.Put(strconv.Itoa(i), i); err != nil {
128-
l.log.Printf("[ERROR] Failed to call Put command for %d: %v", i, err)
132+
b.log.Printf("[ERROR] Failed to call Put command for %d: %v", i, err)
129133
}
130134
case strings.ToLower(cmd) == "get":
131135
_, err := dm.Get(strconv.Itoa(i))
132136
if err != nil {
133-
l.log.Printf("[ERROR] Failed to call Get command for %d: %v", i, err)
137+
b.log.Printf("[ERROR] Failed to call Get command for %d: %v", i, err)
134138
}
135139
case strings.ToLower(cmd) == "delete":
136140
err := dm.Delete(strconv.Itoa(i))
137141
if err != nil {
138-
l.log.Printf("[ERROR] Failed to call Delete command for %d: %v", i, err)
142+
b.log.Printf("[ERROR] Failed to call Delete command for %d: %v", i, err)
139143
}
140144
case strings.ToLower(cmd) == "incr":
141145
_, err := dm.Incr(strconv.Itoa(i), 1)
142146
if err != nil {
143-
l.log.Printf("[ERROR] Failed to call Incr command for %d: %v", i, err)
147+
b.log.Printf("[ERROR] Failed to call Incr command for %d: %v", i, err)
144148
}
145149
case strings.ToLower(cmd) == "decr":
146150
_, err := dm.Decr(strconv.Itoa(i), 1)
147151
if err != nil {
148-
l.log.Printf("[ERROR] Failed to call Decr command for %d: %v", i, err)
152+
b.log.Printf("[ERROR] Failed to call Decr command for %d: %v", i, err)
149153
}
150154
}
151155

152156
response := time.Since(now)
153-
l.mu.Lock()
154-
l.responses = append(l.responses, response)
155-
l.mu.Unlock()
157+
b.mu.Lock()
158+
b.responses = append(b.responses, response)
159+
b.mu.Unlock()
156160
}
157161
}
158162

159-
func (l *Loader) Run(cmd string) error {
163+
func (b *Benchmark) Run(cmd string) error {
160164
if cmd == "" {
161165
return fmt.Errorf("no command given")
162166
}
@@ -172,19 +176,19 @@ func (l *Loader) Run(cmd string) error {
172176

173177
var elapsed time.Duration
174178
ch := make(chan int)
175-
for i := 0; i < l.numClients; i++ {
176-
l.wg.Add(1)
177-
go l.worker(cmd, ch)
179+
for i := 0; i < b.connections; i++ {
180+
b.wg.Add(1)
181+
go b.worker(cmd, ch)
178182
}
179183

180184
now := time.Now()
181-
for i := 0; i < l.numRequests; i++ {
185+
for i := 0; i < b.requests; i++ {
182186
ch <- i
183187
}
184188
close(ch)
185-
l.wg.Wait()
189+
b.wg.Wait()
186190

187191
elapsed = time.Since(now)
188-
l.stats(cmd, elapsed)
192+
b.stats(cmd, elapsed)
189193
return nil
190194
}

0 commit comments

Comments
 (0)