FastBinaryEncoding icon indicating copy to clipboard operation
FastBinaryEncoding copied to clipboard

Benchmark Java Serialisation / Deserialization Speeds Against ActiveJ Serialisation

Open sirinath opened this issue 3 years ago • 4 comments

To ensure this is actually "Fast" Binery Encoding please benchmark serialisation speeds against https://serializer.activej.io/

sirinath avatar Feb 16 '21 09:02 sirinath

We're not competing with native language serializers, because we're cross platform, cross language and cross wire.

The fastest serialize will be memcpy(sizeof(MyStruct)) in C++ :-)

chronoxor avatar Feb 16 '21 10:02 chronoxor

Colfer serialisation (https://github.com/pascaldekloe/colfer) is the fastest cross platform serialisation which you can use for benchmarking. But it would be worth while to see how you hold up with language specific implementations also.

sirinath avatar Feb 16 '21 15:02 sirinath

It was easy to benchmark the same model as Colfer serialization does for testing the serialization performance.

bench.fbe:

package bench
version 1.0

struct Benchmark
{
    int64 key;
    string host;
    int32 port;
    int64 sise;
    uint64 hash;
    double ratio;
    bool route;
}

serialize_bench.cpp:

#include "benchmark/cppbenchmark.h"
#include "../proto/bench_models.h"

class SerializationFixture
{
protected:
    FBE::bench::BenchmarkModel writer;
    std::vector<bench::Benchmark> benchmarks;
    size_t index{0};
    size_t size{4};

    SerializationFixture()
    {
        benchmarks.emplace_back(bench::Benchmark(1234567890, "db003lz12", 389, 452, 0x488b5c2428488918, 0.99, true));
        benchmarks.emplace_back(bench::Benchmark(1234567891, "localhost", 22, 4096, 0x243048899c24c824, 0.20, false));
        benchmarks.emplace_back(bench::Benchmark(1234567892, "kdc.local", 88, 1984, 0x000048891c24485c, 0.06, false));
        benchmarks.emplace_back(bench::Benchmark(1234567893, "vhost8.dmz.example.com", 27017, 59741, 0x5c2408488b9c2489, 0.0, true));
    }
};

BENCHMARK_FIXTURE(SerializationFixture, "Serialize")
{
    // Reset writer stream
    writer.reset();

    // Serialize
    writer.serialize(benchmarks[index++ % size]);
}

BENCHMARK_MAIN()

deserialize_bench.cpp:

#include "benchmark/cppbenchmark.h"
#include "../proto/bench_models.h"

class DeserializationFixture
{
protected:
    FBE::bench::BenchmarkModel writer;
    FBE::bench::BenchmarkModel reader;
    bench::Benchmark deserialized;
    size_t index{0};
    size_t size{4};

    DeserializationFixture()
    {
        std::vector<bench::Benchmark> benchmarks;
        benchmarks.emplace_back(bench::Benchmark(1234567890, "db003lz12", 389, 452, 0x488b5c2428488918, 0.99, true));
        benchmarks.emplace_back(bench::Benchmark(1234567891, "localhost", 22, 4096, 0x243048899c24c824, 0.20, false));
        benchmarks.emplace_back(bench::Benchmark(1234567892, "kdc.local", 88, 1984, 0x000048891c24485c, 0.06, false));
        benchmarks.emplace_back(bench::Benchmark(1234567893, "vhost8.dmz.example.com", 27017, 59741, 0x5c2408488b9c2489, 0.0, true));

        for (const auto& benchmark : benchmarks)
            writer.serialize(benchmark);
        assert(writer.verify() && "Model is broken!");
        reader.attach(writer.buffer());
        assert(reader.verify() && "Model is broken!");
    }
};

BENCHMARK_FIXTURE(DeserializationFixture, "Deserialize")
{
    // Deserialize
    reader.deserialize(deserialized);

    ++index;

    // Reset reader stream
    if (index == size)
        reader.attach(writer.buffer());
}

BENCHMARK_MAIN()

chronoxor avatar Feb 16 '21 17:02 chronoxor

Serialization benchmark results:

Phase: Serialize
Average time: 31 ns/op
Minimal time: 37 ns/op
Maximal time: 39 ns/op
Total time: 2.667 s
Total operations: 86009850
Operations throughput: 32239885 ops/s

Deserialization benchmark results:

Phase: Deserialize
Average time: 18 ns/op
Minimal time: 21 ns/op
Maximal time: 22 ns/op
Total time: 1.871 s
Total operations: 101784438
Operations throughput: 54389865 ops/s

chronoxor avatar Feb 16 '21 17:02 chronoxor