latency.cpp 5.02 KB
Newer Older
gabime's avatar
gabime committed
1 2 3 4 5 6 7 8
//
// Copyright(c) 2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// latency.cpp : spdlog latency benchmarks
//
gabime's avatar
gabime committed
9 10

#include "spdlog/spdlog.h"
gabime's avatar
gabime committed
11 12 13 14 15
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
gabime's avatar
gabime committed
16

gabime's avatar
gabime committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include "utils.h"
#include <atomic>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

gabime's avatar
gabime committed
34
int main(int, char *[])
gabime's avatar
gabime committed
35
{
gabime's avatar
gabime committed
36
    std::srand(static_cast<unsigned>(std::time(nullptr))); // use current time as seed for random generator
gabime's avatar
gabime committed
37
    int howmany = 1000000;
gabime's avatar
gabime committed
38 39
    int queue_size = howmany + 2;
    int threads = 10;
40 41
    size_t file_size = 30 * 1024 * 1024;
    size_t rotating_files = 5;
gabime's avatar
gabime committed
42 43 44 45

    try
    {

gabime's avatar
gabime committed
46 47
        cout << "******************************************************************"
                "*************\n";
gabime's avatar
gabime committed
48
        cout << "Single thread\n";
gabime's avatar
gabime committed
49 50
        cout << "******************************************************************"
                "*************\n";
gabime's avatar
gabime committed
51 52 53 54 55 56 57 58 59 60 61 62

        auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true);
        bench(howmany, basic_st);

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
        bench(howmany, rotating_st);

        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
        bench(howmany, daily_st);

        bench(howmany, spdlog::create<null_sink_st>("null_st"));

gabime's avatar
gabime committed
63 64
        cout << "\n****************************************************************"
                "***************\n";
gabime's avatar
gabime committed
65
        cout << threads << " threads sharing same logger\n";
gabime's avatar
gabime committed
66 67
        cout << "******************************************************************"
                "*************\n";
gabime's avatar
gabime committed
68 69 70 71 72 73 74 75 76 77 78

        auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
        bench_mt(howmany, basic_mt, threads);

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

gabime's avatar
gabime committed
79 80
        cout << "\n****************************************************************"
                "***************\n";
gabime's avatar
gabime committed
81
        cout << "async logging.. " << threads << " threads sharing same logger\n";
gabime's avatar
gabime committed
82 83
        cout << "******************************************************************"
                "*************\n";
gabime's avatar
gabime committed
84 85 86

        for (int i = 0; i < 3; ++i)
        {
87
            spdlog::init_thread_pool(static_cast<size_t>(queue_size), 1);
gabime's avatar
gabime committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
            auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
            bench_mt(howmany, as, threads);
            spdlog::drop("async");
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    using namespace std::chrono;
    using chrono::high_resolution_clock;
    using chrono::milliseconds;
    using chrono::nanoseconds;

    cout << log->name() << "...\t\t" << flush;
    nanoseconds total_nanos = nanoseconds::zero();
    for (auto i = 0; i < howmany; ++i)
    {
        auto start = high_resolution_clock::now();
        log->info("Hello logger: msg number {}", i);
        auto delta_nanos = chrono::duration_cast<nanoseconds>(high_resolution_clock::now() - start);
gabime's avatar
gabime committed
116
        total_nanos += delta_nanos;
gabime's avatar
gabime committed
117 118
    }

gabime's avatar
gabime committed
119
    auto avg = total_nanos.count() / howmany;
gabime's avatar
gabime committed
120 121 122 123 124 125 126 127 128 129 130 131
    cout << format(avg) << " ns/call" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
    using namespace std::chrono;
    using chrono::high_resolution_clock;
    using chrono::milliseconds;
    using chrono::nanoseconds;

    cout << log->name() << "...\t\t" << flush;
    vector<thread> threads;
gabime's avatar
gabime committed
132
    std::atomic<nanoseconds::rep> total_nanos{0};
gabime's avatar
gabime committed
133 134 135 136 137 138 139 140
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (int j = 0; j < howmany / thread_count; j++)
            {
                auto start = high_resolution_clock::now();
                log->info("Hello logger: msg number {}", j);
                auto delta_nanos = chrono::duration_cast<nanoseconds>(high_resolution_clock::now() - start);
gabime's avatar
gabime committed
141
                total_nanos += delta_nanos.count();
gabime's avatar
gabime committed
142 143 144 145 146 147 148 149 150
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

gabime's avatar
gabime committed
151
    auto avg = total_nanos / howmany;
gabime's avatar
gabime committed
152 153
    cout << format(avg) << " ns/call" << endl;
}