Add Criterion benchmarks
Introduces a (hopefully) representative set of benchmarks for an imaginary 'User session token', with a variable size depending on which fields are populated. Does not yet cover floating point or union types. Also included is a go-bare implementation of an identical benchmark, so that we can compare our implementation again the 'reference' code.
This commit is contained in:
parent
2e330a7e37
commit
c74cc25a2f
|
@ -11,3 +11,12 @@ categories = ["encoding"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_derive = "1.0"
|
||||||
|
serde_bytes = "0.11"
|
||||||
|
criterion = "0.3"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "user_sessions"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Provided so users not familiar with Go don't need to know the go bench invocation
|
||||||
|
|
||||||
|
.PHONY: bench go-bench
|
||||||
|
|
||||||
|
bench:
|
||||||
|
cargo bench
|
||||||
|
|
||||||
|
go-bench:
|
||||||
|
cd benches/go-reference && go test -bench=.
|
||||||
|
|
||||||
|
bench-all: bench go-bench
|
8
README
8
README
|
@ -4,6 +4,14 @@ An implementation of the BARE (https://git.sr.ht/~sircmpwn/bare) encoding format
|
||||||
|
|
||||||
Mailing list: https://lists.sr.ht/~tdeo/serde_bare
|
Mailing list: https://lists.sr.ht/~tdeo/serde_bare
|
||||||
|
|
||||||
|
To run benchmarks on your system:
|
||||||
|
|
||||||
|
make bench
|
||||||
|
|
||||||
|
Or to run the reference Go benchmarks as well:
|
||||||
|
|
||||||
|
make bench-all
|
||||||
|
|
||||||
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
|
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module git.sr.ht/~tdeo/serde_bare/benches/go-reference
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require git.sr.ht/~sircmpwn/go-bare v0.0.0-20200623145341-debb068b456a
|
|
@ -0,0 +1,15 @@
|
||||||
|
git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw=
|
||||||
|
git.sr.ht/~sircmpwn/go-bare v0.0.0-20200623145341-debb068b456a h1:bqT/ygbVtD6b/B/skCQ+hZI4OtwuyKFQJxwS3z1lY3g=
|
||||||
|
git.sr.ht/~sircmpwn/go-bare v0.0.0-20200623145341-debb068b456a/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA=
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,120 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"git.sr.ht/~sircmpwn/go-bare"
|
||||||
|
"log"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserRole uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
Admin UserRole = 0
|
||||||
|
Normal = 1
|
||||||
|
Guest = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Token []byte
|
||||||
|
Expires uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID uint
|
||||||
|
Name string
|
||||||
|
Email string
|
||||||
|
Role UserRole
|
||||||
|
Session *Session
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeAdmin() ([]byte, User) {
|
||||||
|
session := Session{
|
||||||
|
Token: []byte("a2b08ecd0a0dc594ebccd607033e79262d1fa049a6d44165631b10028f97b611"),
|
||||||
|
Expires: 42424242,
|
||||||
|
}
|
||||||
|
|
||||||
|
admin := User{
|
||||||
|
ID: 42,
|
||||||
|
Name: "Jane Doe",
|
||||||
|
Email: "jdoe@example.com",
|
||||||
|
Role: Admin,
|
||||||
|
Session: &session,
|
||||||
|
}
|
||||||
|
|
||||||
|
marshalled, err := bare.Marshal(&admin)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to marshal: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return marshalled, admin
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGuest() ([]byte, User) {
|
||||||
|
guest := User{
|
||||||
|
ID: 112,
|
||||||
|
Name: "John Smith",
|
||||||
|
Email: "john@example.com",
|
||||||
|
Role: Guest,
|
||||||
|
Session: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
marshalled, err := bare.Marshal(&guest)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to marshal: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return marshalled, guest
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAdminSerialize(b *testing.B) {
|
||||||
|
s, admin := makeAdmin()
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.Grow(128)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.SetBytes(int64(len(s)))
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
w := bare.NewWriter(&buf)
|
||||||
|
bare.MarshalWriter(w, admin)
|
||||||
|
buf.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAdminDeserialize(b *testing.B) {
|
||||||
|
s, _ := makeAdmin()
|
||||||
|
var output User
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.SetBytes(int64(len(s)))
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
_ = bare.Unmarshal(s, &output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGuestSerialize(b *testing.B) {
|
||||||
|
s, guest := makeGuest()
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.Grow(128)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.SetBytes(int64(len(s)))
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
w := bare.NewWriter(&buf)
|
||||||
|
bare.MarshalWriter(w, guest)
|
||||||
|
buf.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGuestDeserialize(b *testing.B) {
|
||||||
|
s, _ := makeGuest()
|
||||||
|
var output User
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.SetBytes(int64(len(s)))
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
_ = bare.Unmarshal(s, &output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
enum UserRole {
|
||||||
|
Admin,
|
||||||
|
User,
|
||||||
|
Guest,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
struct Session {
|
||||||
|
#[serde(with = "serde_bytes")]
|
||||||
|
token: Vec<u8>,
|
||||||
|
expires: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
struct User {
|
||||||
|
id: u32,
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
role: UserRole,
|
||||||
|
session: Option<Session>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn admin_sample() -> (User, Vec<u8>) {
|
||||||
|
let sample = User {
|
||||||
|
id: 42,
|
||||||
|
name: "Jane Doe".to_string(),
|
||||||
|
email: "jdoe@example.com".to_string(),
|
||||||
|
role: UserRole::Admin,
|
||||||
|
session: Some(Session {
|
||||||
|
token: b"a2b08ecd0a0dc594ebccd607033e79262d1fa049a6d44165631b10028f97b611".to_vec(),
|
||||||
|
expires: 42424242,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
let ser = serde_bare::to_vec(&sample).unwrap();
|
||||||
|
(sample, ser)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guest_sample() -> (User, Vec<u8>) {
|
||||||
|
let sample = User {
|
||||||
|
id: 112,
|
||||||
|
name: "John Doe".to_string(),
|
||||||
|
email: "john@example.com".to_string(),
|
||||||
|
role: UserRole::Guest,
|
||||||
|
session: None,
|
||||||
|
};
|
||||||
|
let ser = serde_bare::to_vec(&sample).unwrap();
|
||||||
|
(sample, ser)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_admin(c: &mut Criterion) {
|
||||||
|
let (sample, ser) = admin_sample();
|
||||||
|
let mut group = c.benchmark_group("serialization");
|
||||||
|
group.throughput(Throughput::Bytes(ser.len() as u64));
|
||||||
|
|
||||||
|
let mut buffer: [u8; 128] = [0; 128];
|
||||||
|
group.bench_function("serialize admin", |b| {
|
||||||
|
b.iter(|| serde_bare::to_writer(&mut buffer[..], &sample).unwrap())
|
||||||
|
});
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_admin(c: &mut Criterion) {
|
||||||
|
let (_, ser) = admin_sample();
|
||||||
|
let mut group = c.benchmark_group("deserialization");
|
||||||
|
group.throughput(Throughput::Bytes(ser.len() as u64));
|
||||||
|
|
||||||
|
group.bench_function("deserialize admin", |b| {
|
||||||
|
b.iter(|| serde_bare::from_slice::<User>(&ser).unwrap())
|
||||||
|
});
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_guest(c: &mut Criterion) {
|
||||||
|
let (sample, ser) = guest_sample();
|
||||||
|
let mut group = c.benchmark_group("serialization");
|
||||||
|
group.throughput(Throughput::Bytes(ser.len() as u64));
|
||||||
|
|
||||||
|
let mut buffer: [u8; 128] = [0; 128];
|
||||||
|
group.bench_function("serialize guest", |b| {
|
||||||
|
b.iter(|| serde_bare::to_writer(&mut buffer[..], &sample).unwrap())
|
||||||
|
});
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_guest(c: &mut Criterion) {
|
||||||
|
let (_, ser) = guest_sample();
|
||||||
|
let mut group = c.benchmark_group("deserialization");
|
||||||
|
group.throughput(Throughput::Bytes(ser.len() as u64));
|
||||||
|
|
||||||
|
group.bench_function("deserialize guest", |b| {
|
||||||
|
b.iter(|| serde_bare::from_slice::<User>(&ser).unwrap())
|
||||||
|
});
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(admin, serialize_admin, deserialize_admin);
|
||||||
|
criterion_group!(guest, serialize_guest, deserialize_guest);
|
||||||
|
criterion_main!(admin, guest);
|
Loading…
Reference in New Issue