Skip to content

Performance compare with native dragonbox::to_chars #3675

Open
@zhiqiang-hhhh

Description

@zhiqiang-hhhh

Hello, I am using dragonbox::to_chars as my float pointer number to string method, and trying to replace dragonbox with lib fmt 10.x since it has already integrated with dragonbox and lib fmt has more output format control.

But according to my simple benchmark, dragonbox is almost x1.7 faster than lib fmt when doing float-point to string.

#include <gtest/gtest.h>
#include <fmt/format.h>
#include <dragonbox/dragonbox_to_chars.h>
#include <random>

class PerformanceTest : public ::testing::Test {
protected:
    void SetUp() override {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<double> dis_double(-100000.0, +100000.0);
        std::uniform_real_distribution<float> dis_float(-100000.0, +100000.0);
        
        for (int i = 0; i < 100000000; ++i) {
            values_double.push_back(dis_double(gen));
            values_float.push_back(dis_float(gen));
        }
    }

    void TearDown() override {
    }

    std::vector<double> values_double;
    std::vector<float> values_float;
};

TEST_F(PerformanceTest, FmtPerformanceDouble) {
    char buffer[20];

    for (const auto& value : values_double) {
        auto res = fmt::format_to(buffer, "{}", value);
        *res = '\0';
    }
}

TEST_F(PerformanceTest, DragonboxPerformanceDouble) {
    char buffer[20];

    for (const auto& value : values_double) {
        jkj::dragonbox::to_chars(value, buffer);
    }
}


TEST_F(PerformanceTest, FmtPerformanceFloat) {
    char buffer[20];

    for (const auto& value : values_float) {
        auto res = fmt::format_to(buffer, "{}", value);
        *res = '\0';
    }
}

TEST_F(PerformanceTest, DragonboxPerformanceFloat) {
    char buffer[20];

    for (const auto& value : values_double) {
        jkj::dragonbox::to_chars(value, buffer);
    }
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

build with release, result:

[==========] Running 4 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 4 tests from PerformanceTest
[ RUN      ] PerformanceTest.FmtPerformanceDouble
[       OK ] PerformanceTest.FmtPerformanceDouble (11391 ms)
[ RUN      ] PerformanceTest.DragonboxPerformanceDouble
[       OK ] PerformanceTest.DragonboxPerformanceDouble (6636 ms)
[ RUN      ] PerformanceTest.FmtPerformanceFloat
[       OK ] PerformanceTest.FmtPerformanceFloat (10185 ms)
[ RUN      ] PerformanceTest.DragonboxPerformanceFloat
[       OK ] PerformanceTest.DragonboxPerformanceFloat (6649 ms)
[----------] 4 tests from PerformanceTest (34864 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 1 test suite ran. (34864 ms total)
[  PASSED  ] 4 tests.

According to my basic knowledge, time consumption of float point to decimal should be almost same after lib fmt integrated with dragon box. so the determining factor of performance difference here should be the output formatting control?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions