Repository: ClickHouse/ClickHouse
File: src/Parsers/examples/parser_memory_profiler.cpp (C++)

Code before:
    sz = sizeof(prof_enabled);
    ret = mallctl("opt.prof", &prof_enabled, &sz, nullptr, 0);
    std::cerr << "  opt.prof (profiling enabled at runtime): " << (ret == 0 ? (prof_enabled ? "yes" : "no") : "error") << "\n";

    if (!prof_compiled)
    {
        std::cerr << "\nProfiling is not available. jemalloc was compiled without JEMALLOC_PROF.\n";
        std::cerr << "On Linux builds, profiling should be available.\n";
        std::cerr << "On macOS, profiling support is limited.\n";
    }
    else if (!prof_enabled)
    {
        std::cerr << "\nProfiler is compiled but not enabled. This must be set at startup.\n";
        std::cerr << "\nOn macOS (jemalloc with je_ prefix), use JE_MALLOC_CONF:\n";
        std::cerr << "  JE_MALLOC_CONF=prof:true,prof_active:true <program> --profile <prefix>\n";
        std::cerr << "\nOn Linux (jemalloc without prefix), use MALLOC_CONF:\n";
        std::cerr << "  MALLOC_CONF=prof:true <program> --profile <prefix>\n";
    }
}

}


int main(int argc, char ** argv)
try
{
    using namespace DB;

    std::string profile_prefix;
    bool enable_profiling = false;
    bool enable_symbolize = false;

    for (int i = 1; i < argc; ++i)
    {
        std::string arg = argv[i];
        if (arg == "--profile" && i + 1 < argc)
        {
            profile_prefix = argv[++i];
            enable_profiling = true;
        }
        else if (arg == "--symbolize")
        {
            enable_symbolize = true;
        }
        else if (arg == "--help" || arg == "-h")
        {
            printUsage(argv[0]);
            return 0;
        }
        else
        {

Review comment (suggestion):
I guess you can use one option for both with multitoken, or you can also mark it as positional, then you can specify it like `a.out sym1.heap sym2.heap`

Code after:
    {
        std::cerr << "\nProfiler is compiled but not enabled. This must be set at startup.\n";
        std::cerr << "\nOn macOS (jemalloc with je_ prefix), use JE_MALLOC_CONF:\n";
        std::cerr << "  JE_MALLOC_CONF=prof:true,prof_active:true <program> --profile <prefix>\n";
        std::cerr << "\nOn Linux (jemalloc without prefix), use MALLOC_CONF:\n";
        std::cerr << "  MALLOC_CONF=prof:true <program> --profile <prefix>\n";
    }
}

}


int main(int argc, char ** argv)
try
{
    using namespace DB;

    po::options_description desc("Measure memory allocations during SQL parsing.\n"
                                 "Reads query from stdin, prints tab-separated: query_length before after diff\n\n"
                                 "Options");
    desc.add_options()
        ("help,h", "Show help")
        ("profile", po::value<std::string>(), "Dump jemalloc heap profiles with this prefix")
        ("symbolize", "Symbolize heap profiles (requires --profile)")
        ("symbolize-batch", po::value<std::vector<std::string>>()->multitoken(),
         "Batch-symbolize .heap files (shared cache via global LRU)")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.contains("help"))
    {
        std::cerr << desc << "\n";
        return 0;
    }

    /// Handle batch symbolization mode: global LRU cache is shared across calls
    if (vm.contains("symbolize-batch"))
    {
        auto batch_files = vm["symbolize-batch"].as<std::vector<std::string>>();
        if (batch_files.empty())
        {
            std::cerr << "Error: --symbolize-batch requires at least one .heap file\n";
            return 1;
        }

        for (const auto & file : batch_files)
        {
            if (!std::filesystem::exists(file))