Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5196fed4 authored by Daniel Zheng's avatar Daniel Zheng Committed by Automerger Merge Worker
Browse files

Merge "Add unit test for cow compressor performance" into main am: f278b547...

Merge "Add unit test for cow compressor performance" into main am: f278b547 am: b1cbaa77 am: fef270e8

Original change: https://android-review.googlesource.com/c/platform/system/core/+/2722633



Change-Id: Iaa226d2bf8911d363c7efc8f96c16cd4c3785efd
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents cfa18e29 fef270e8
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#pragma once

#include <memory>
#include <string_view>
#include "libsnapshot/cow_format.h"

namespace android {
+22 −0
Original line number Diff line number Diff line

cc_binary {
    name: "cow_benchmark",
    host_supported: true,
    defaults: [
        "fs_mgr_defaults",
        "libsnapshot_cow_defaults",
    ],

    srcs: ["cow_benchmark.cpp"],

    static_libs: [
        "libsnapshot_cow",
    ],

    shared_libs: [
        "libbase",
        "liblog",
    ],

    cflags: ["-Werror"],
}
+188 −0
Original line number Diff line number Diff line

#include <memory>

#include <array>
#include <iostream>
#include <random>

#include <libsnapshot/cow_compress.h>
#include <libsnapshot/cow_format.h>

static const uint32_t BLOCK_SZ = 4096;
static const uint32_t SEED_NUMBER = 10;

namespace android {
namespace snapshot {

static std::string CompressionToString(CowCompression& compression) {
    std::string output;
    switch (compression.algorithm) {
        case kCowCompressBrotli:
            output.append("brotli");
            break;
        case kCowCompressGz:
            output.append("gz");
            break;
        case kCowCompressLz4:
            output.append("lz4");
            break;
        case kCowCompressZstd:
            output.append("zstd");
            break;
        case kCowCompressNone:
            return "No Compression";
    }
    output.append(" " + std::to_string(compression.compression_level));
    return output;
}

void OneShotCompressionTest() {
    std::cout << "\n-------One Shot Compressor Perf Analysis-------\n";

    std::vector<CowCompression> compression_list = {
            {kCowCompressLz4, 0},     {kCowCompressBrotli, 1}, {kCowCompressBrotli, 3},
            {kCowCompressBrotli, 11}, {kCowCompressZstd, 3},   {kCowCompressZstd, 6},
            {kCowCompressZstd, 9},    {kCowCompressZstd, 22},  {kCowCompressGz, 1},
            {kCowCompressGz, 3},      {kCowCompressGz, 6},     {kCowCompressGz, 9}};
    std::vector<std::unique_ptr<ICompressor>> compressors;
    for (auto i : compression_list) {
        compressors.emplace_back(ICompressor::Create(i, BLOCK_SZ));
    }

    // Allocate a buffer of size 8 blocks.
    std::array<char, 32768> buffer;

    // Generate a random 4k buffer of characters
    std::default_random_engine gen(SEED_NUMBER);
    std::uniform_int_distribution<int> distribution(0, 10);
    for (int i = 0; i < buffer.size(); i++) {
        buffer[i] = static_cast<char>(distribution(gen));
    }

    std::vector<std::pair<double, std::string>> latencies;
    std::vector<std::pair<double, std::string>> ratios;

    for (size_t i = 0; i < compressors.size(); i++) {
        const auto start = std::chrono::steady_clock::now();
        std::basic_string<uint8_t> compressed_data =
                compressors[i]->Compress(buffer.data(), buffer.size());
        const auto end = std::chrono::steady_clock::now();
        const auto latency =
                std::chrono::duration_cast<std::chrono::nanoseconds>(end - start) / 1000.0;
        const double compression_ratio =
                static_cast<uint16_t>(compressed_data.size()) * 1.00 / buffer.size();

        std::cout << "Metrics for " << CompressionToString(compression_list[i]) << ": latency -> "
                  << latency.count() << "ms "
                  << " compression ratio ->" << compression_ratio << " \n";

        latencies.emplace_back(
                std::make_pair(latency.count(), CompressionToString(compression_list[i])));
        ratios.emplace_back(
                std::make_pair(compression_ratio, CompressionToString(compression_list[i])));
    }

    int best_speed = 0;
    int best_ratio = 0;

    for (size_t i = 1; i < latencies.size(); i++) {
        if (latencies[i].first < latencies[best_speed].first) {
            best_speed = i;
        }
        if (ratios[i].first < ratios[best_ratio].first) {
            best_ratio = i;
        }
    }

    std::cout << "BEST SPEED: " << latencies[best_speed].first << "ms "
              << latencies[best_speed].second << "\n";
    std::cout << "BEST RATIO: " << ratios[best_ratio].first << " " << ratios[best_ratio].second
              << "\n";
}

void IncrementalCompressionTest() {
    std::cout << "\n-------Incremental Compressor Perf Analysis-------\n";

    std::vector<CowCompression> compression_list = {
            {kCowCompressLz4, 0},     {kCowCompressBrotli, 1}, {kCowCompressBrotli, 3},
            {kCowCompressBrotli, 11}, {kCowCompressZstd, 3},   {kCowCompressZstd, 6},
            {kCowCompressZstd, 9},    {kCowCompressZstd, 22},  {kCowCompressGz, 1},
            {kCowCompressGz, 3},      {kCowCompressGz, 6},     {kCowCompressGz, 9}};
    std::vector<std::unique_ptr<ICompressor>> compressors;
    for (auto i : compression_list) {
        compressors.emplace_back(ICompressor::Create(i, BLOCK_SZ));
    }

    // Allocate a buffer of size 8 blocks.
    std::array<char, 32768> buffer;

    // Generate a random 4k buffer of characters
    std::default_random_engine gen(SEED_NUMBER);
    std::uniform_int_distribution<int> distribution(0, 10);
    for (int i = 0; i < buffer.size(); i++) {
        buffer[i] = static_cast<char>(distribution(gen));
    }

    std::vector<std::pair<double, std::string>> latencies;
    std::vector<std::pair<double, std::string>> ratios;

    for (size_t i = 0; i < compressors.size(); i++) {
        std::vector<std::basic_string<uint8_t>> compressed_data_vec;
        int num_blocks = buffer.size() / BLOCK_SZ;
        const uint8_t* iter = reinterpret_cast<const uint8_t*>(buffer.data());

        const auto start = std::chrono::steady_clock::now();
        while (num_blocks > 0) {
            std::basic_string<uint8_t> compressed_data = compressors[i]->Compress(iter, BLOCK_SZ);
            compressed_data_vec.emplace_back(compressed_data);
            num_blocks--;
            iter += BLOCK_SZ;
        }

        const auto end = std::chrono::steady_clock::now();
        const auto latency =
                std::chrono::duration_cast<std::chrono::nanoseconds>(end - start) / 1000.0;

        size_t size = 0;
        for (auto& i : compressed_data_vec) {
            size += i.size();
        }
        const double compression_ratio = size * 1.00 / buffer.size();

        std::cout << "Metrics for " << CompressionToString(compression_list[i]) << ": latency -> "
                  << latency.count() << "ms "
                  << " compression ratio ->" << compression_ratio << " \n";

        latencies.emplace_back(
                std::make_pair(latency.count(), CompressionToString(compression_list[i])));
        ratios.emplace_back(
                std::make_pair(compression_ratio, CompressionToString(compression_list[i])));
    }

    int best_speed = 0;
    int best_ratio = 0;

    for (size_t i = 1; i < latencies.size(); i++) {
        if (latencies[i].first < latencies[best_speed].first) {
            best_speed = i;
        }
        if (ratios[i].first < ratios[best_ratio].first) {
            best_ratio = i;
        }
    }

    std::cout << "BEST SPEED: " << latencies[best_speed].first << "ms "
              << latencies[best_speed].second << "\n";
    std::cout << "BEST RATIO: " << ratios[best_ratio].first << " " << ratios[best_ratio].second
              << "\n";
}

}  // namespace snapshot
}  // namespace android

int main() {
    android::snapshot::OneShotCompressionTest();
    android::snapshot::IncrementalCompressionTest();

    return 0;
}
 No newline at end of file