使用 boost::json 的快速简单的 C++ JSONLines 处理器

此示例将解析 jsonlines 文件(每行一个 JSON 对象的文件)并打印每个对象的 name 字段。

此代码没有专门针对性能进行优化,而是作为性能和可读性之间的权衡。对于大多数用例来说应该足够快。

jsonlines_processor.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <boost/json.hpp>

class JSONLineProcessor {
public:
    JSONLineProcessor(const std::string& filename) : file(filename) {
        if (!file.is_open()) {
            throw std::runtime_error("Error: Could not open file.");
        }
    }

    void process_lines() {
        std::string line;
        while (std::getline(file, line)) {
            process_line(line);
        }
    }

private:
    std::ifstream file;

    void process_line(const std::string& line) {
        try {
            // Parse the JSON line
            boost::json::value json_value = boost::json::parse(line);

            // Check if it's a JSON object
            if (json_value.is_object()) {
                process_json(json_value.as_object());
            } else {
                std::cerr << "Error: Parsed value is not a JSON object." << std::endl;
            }
        } catch (const boost::json::system_error& e) {
            // Handle parsing errors
            std::cerr << "Error parsing JSON line: " << e.what() << std::endl;
        }
    }

    void process_json(const boost::json::object& obj) {
        // For the sake of example, just print the json["timestamp"] value
        auto _timestamp = obj.at("timestamp");
        if (_timestamp.is_double()) {
            double timestamp = obj.at("timestamp").as_double();

            std::cout << obj.at("timestamp").as_double() << std::endl;
        }
    }
};

int main(int argc, char** argv) {
    if(argc <= 1) {
        std::cerr << "Usage: " << argv[0] << std::endl;
        return 1;
    }

    try {
        JSONLineProcessor processor(argv[1]);
        processor.process_lines();
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }

    return 0;
}

如何编译

compile_jsonlines_processor.sh
g++ -O3 -std=c++17 -lboost_json -o jsonlines_processor jsonlines_processor.cpp

性能

使用以下命令编译

compile_jsonlines_optimized.sh
g++ -march=native -O2 -std=gnu++17 -lboost_json -o jsonlines_processor jsonlines_processor.cpp

并运行

run_jsonlines_benchmark.sh
time ./jsonlines_processor filename.jsonlines > /dev/null

在 4.5GB 的 jsonlines 文件(4442720 行,即 4.4M 行)上运行需要 36.4 秒(3 次运行中的最佳结果),在我的 Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz 上实现了 123.6 MB/s 的吞吐量和每秒 122k JSON 行的处理速度。

此程序不使用多线程


Check out similar posts by category: C/C++, Boost, JSON