Skip to content

Commit

Permalink
Add benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiu128 committed Apr 24, 2024
1 parent e8e2a13 commit d490b60
Show file tree
Hide file tree
Showing 8 changed files with 727 additions and 0 deletions.
7 changes: 7 additions & 0 deletions benchmarks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.ipynb_checkpoints/
measurements.ipynb
new-workspace.jupyterlab-workspace
*.csv
results*/
*.txt
*.log
147 changes: 147 additions & 0 deletions benchmarks/client-sonic/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package main

import (
"encoding/binary"
"flag"
"fmt"
"math"
"os"
"runtime"
"runtime/debug"
"time"

"github.com/talostrading/sonic"
"github.com/talostrading/sonic/sonicerrors"
"github.com/talostrading/sonic/util"
)

var (
n = flag.Int("n", 10, "number of connections")
cpu = flag.Int("cpu", 5, "cpu to pin to")
samples = flag.Int("samples", 1024, "number of samples to record")
rate = flag.Int("rate", 0, "rate")

done = 0
)

type Conn struct {
ioc *sonic.IO
b []byte
conn sonic.Conn
id int
period int64 // nanos
lastTime int64 // nanos epoch

ignore int
index int
samples []time.Duration
}

func NewConn(ioc *sonic.IO, id int) (c *Conn, err error) {
c = &Conn{
ioc: ioc,
b: make([]byte, 1024),
samples: make([]time.Duration, *samples, *samples),
id: id,
period: math.MaxInt64,
lastTime: 0,
}
c.conn, err = sonic.Dial(ioc, "tcp", "localhost:8080")
if err != nil {
return nil, err
}
c.conn.AsyncReadMulti(c.b, c.OnRead)
return c, nil
}

func (c *Conn) OnRead(err error, n int) {
if err != nil {
if err == sonicerrors.ErrCancelled {
done++
fmt.Println("connection finished", c.id, "min_period", time.Duration(c.period)*time.Nanosecond)
c.conn.Close()
return
} else {
panic(err)
}
}

if n != 1024 {
panic("did not read the entire buffer")
}

if c.ignore < 100 {
c.ignore++
return
}

now := util.GetMonoTimeNanos()
if c.index < len(c.samples) {
c.samples[c.index] = time.Duration(now-int64(binary.LittleEndian.Uint64(c.b))) * time.Nanosecond
c.index++

if c.lastTime > 0 {
diff := now - c.lastTime
if c.period > diff {
c.period = diff
}
}
c.lastTime = now
} else {
c.conn.Cancel()
}
}

func main() {
debug.SetGCPercent(-1)

runtime.LockOSThread()
defer runtime.UnlockOSThread()

flag.Parse()
if *rate == 0 {
panic("rate not provided")
}

if err := util.PinTo(*cpu); err != nil {
panic(err)
} else {
fmt.Println("pinned to CPU", *cpu)
}

fmt.Printf("%d connections, %d samples per connection, rate=%dHz period=%s\n", *n, *samples, *rate, time.Second/time.Duration(*rate))

ioc := sonic.MustIO()
defer ioc.Close()

var conns []*Conn
for i := 0; i < *n; i++ {
fmt.Println("connection", i)
conn, err := NewConn(ioc, i)
if err != nil {
panic(err)
}
conns = append(conns, conn)
}

for {
ioc.PollOne()

if done == *n {
fmt.Println("all connections have finished")
filename := fmt.Sprintf("sonic_%dHz_%d.txt", *rate, *n)
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
panic(err)
}
defer file.Close()
for _, conn := range conns {
for _, sample := range conn.samples {
file.WriteString(fmt.Sprintf("%d\n", sample.Microseconds()))
}
}
fmt.Println("wrote", filename, ", bye :)")
return
}
}
}
113 changes: 113 additions & 0 deletions benchmarks/client-std/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package main

import (
"encoding/binary"
"flag"
"fmt"
"math"
"net"
"os"
"runtime/debug"
"sync"
"time"

"github.com/talostrading/sonic/util"
)

var (
n = flag.Int("n", 10, "number of connections")
samples = flag.Int("samples", 1024, "number of samples to record")
rate = flag.Int("rate", 0, "rate")
)

func handle(id int, conn net.Conn, samples []time.Duration) {
defer conn.Close()

ignore := 0
index := 0
b := make([]byte, 1024)
var (
period int64 = math.MaxInt64
lastTime int64 = 0 // nanos epoch
)

for {
n, err := conn.Read(b)
if err != nil {
panic(err)
}
if n != 1024 {
panic("did not read the entire buffer")
}
if ignore < 100 {
ignore++
continue
}

now := util.GetMonoTimeNanos()
if index < len(samples) {
samples[index] = time.Duration(now-int64(binary.LittleEndian.Uint64(b))) * time.Nanosecond
index++

if lastTime > 0 {
diff := now - lastTime
if period > diff {
period = diff
}
}
lastTime = now
} else {
fmt.Println("connection has finished", id, "min_period", time.Duration(period)*time.Nanosecond)
return
}
}

}

func main() {
debug.SetGCPercent(-1)

flag.Parse()

if *rate == 0 {
panic("rate not provided")
}

fmt.Printf("%d connections, %d samples per connection, rate=%dHz period=%s\n", *n, *samples, *rate, time.Second/time.Duration(*rate))

var (
wg sync.WaitGroup
allSamples [][]time.Duration
)

for i := 0; i < *n; i++ {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
panic(err)
}
connSamples := make([]time.Duration, *samples, *samples)
allSamples = append(allSamples, connSamples)
wg.Add(1)
id := i
go func() {
defer wg.Done()
handle(id, conn, connSamples)
}()
}

wg.Wait()

fmt.Println("all connections have finished")
filename := fmt.Sprintf("std_%dHz_%d.txt", *rate, *n)
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
panic(err)
}
defer file.Close()
for _, samples := range allSamples {
for _, sample := range samples {
file.WriteString(fmt.Sprintf("%d\n", sample.Microseconds()))
}
}
fmt.Println("wrote", filename, ", bye :)")
}
35 changes: 35 additions & 0 deletions benchmarks/run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash


rates=(100 1000 10000 100000)
conns=(1 2 4 8 16 32 64 128 256)

function run() {
which="$1"
echo "running test-suite for ${which}"

for rate in "${rates[@]}"; do
echo "starting server at rate=${rate} for ${which}"
./server/target/release/server "${rate}" > "server_${rate}Hz_${which}.log" &
server_pid=$!

for conn in "${conns[@]}"; do
echo "running ${which} tests rate=${rate} conn=${conn}"
go run client-"${which}"/main.go -n "${conn}" -rate "${rate}"
echo "done"
sleep 5
done

kill $server_pid
echo "done with tests at rate=${rate} for ${which}"

sleep 1
done

sleep 2
}

run "std"
run "sonic"

echo "bye :)"
1 change: 1 addition & 0 deletions benchmarks/server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
Loading

0 comments on commit d490b60

Please sign in to comment.