c++profilerperf

Linux perf does not record function in libstdc++.so correctly


I am using perf to profile a C++ program. The code is like:

std::string generateRandomString() {
    // Initialize a random number generator
    std::random_device rd;
    std::mt19937 gen(rd());

    // Define a distribution for the length of the string (1 to 6)
    std::uniform_int_distribution<> lenDistribution(1, 6);
    int length = lenDistribution(gen);

    // Define characters that can be part of the string
    const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    // Generate the random string
    std::uniform_int_distribution<> charDistribution(0, characters.size() - 1);
    std::string result;
    result.reserve(length);

    for (int i = 0; i < length; ++i) {
        result += characters[charDistribution(gen)];
    }
    return result;
}


void test_trie(){
    for (...) generateRandomString();
}

void test(){
    // do something
}

int main(){
    test_trie();
    test();
}

Then

  1. I compile it with g++ -g -O2 main.cpp -o secmaster_test (-O0 is also tried)
  2. profile it with perf record -F 999 -g -- ./secmaster_test
  3. draw a flamegraph. like this enter image description here

But I think the result should be like follow:

                                           | --- some random -----|
                  | ...something...        | generateRandomString | -- --|
                  | ----------test-------- | --------------test_trie-----|
                  | ---------------------main----------------------------|
|--startup code-- | -------------------secmaster_test------------------- | -- cleanup -- |

Seems that perf somehow don't know functions about random is called in main() ?

BTW, I tried:

  1. using perf record --call-graph dwarf
  2. using perf record --call-graph fp

and failed


Solution

  • Solved with the help of comments and answers.

    Default compilation of stdlibc++ does not contain all frame pointers, so perf captures incorrect frame pointer. The solution is to recompile gcc (for c,c++, to get glibc and libstdc++)

    Hereby is the steps for me:

    1. download gcc 11.4
    2. in gcc root dir, run ./contrib/download_prerequisites to download prerequisites
    3. run mkdir build && cd build && ../configure CXXFLAGS="-g -O2 -D_GNU_SOURCE -fno-omit-frame-pointer" --enable-languages=c,c++ --disable-multilib to configure gcc, maybe add more options like --prefix=/path/to/install
    4. compile and install make -j16 && make install

    Then compile program with new gcc/g++, will give correct FlameGraph.