I'm trying to profile a C++ shared library on Windows 10, in order to find which lines the program is spending most time on. (The code happens to form part of an R package.)
I've previously used
AMD µprof and
Very Sleepy. However, I'm now having trouble compiling the code: all these profilers show is which DLL is being used, rather than which function / line.
I suspect that the problem relates to debugging symbol tables being missing. Per
Enabling debug symbols in shared library using GCC, I've ensured that a -g flag is applied when compiling each file, and that there is no -s flag at the linker stage. What else do I need to do to allow µprof / Very Sleepy to tell me which lines of the code are proving a bottleneck?
Detailed compilation notes
I'm using RBuildTools MinGW-w64 v3 g++ 8.3.0 to compile the code on 64-bit Windows 10.
Here are some sample compile commands, which are being generated by R, using Makevars / Makeconf templates.
g++ -std=gnu++14 -I"<<include paths>>" -DNDEBUG -g -O2 -Wall
-mfpmath=sse -msse2 -mstackrealign
-c source_file.cpp -o source_file.o
g++ -shared -static-libgcc -g -Og
-o PackageName.dll tmp.def source_file.o <<Other files>>
-L<<Library paths>>
I've also tried replacing -g with -gdwarf-2 -g3, and adding -fno-omit-frame-pointer, per Very Sleepy doesn't see function names when capturing MinGW compiled file.
Running without shared library
ssbssa suggested running against a simple executable.
I tried:
#include <chrono>
#include <thread>
#include <iostream>
long sumto(long n) {
if(n > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return n + sumto(n - 1);
}
return 1;
}
int main() {
std::cout << sumto(1000) << std::endl;
return 0;
}
>"C:/RBuildTools/4.0/mingw64/bin/"g++ -std=gnu++14 -gdwarf-2 -g3 -Og -c test.cpp
>"C:/RBuildTools/4.0/mingw64/bin/"g++ -std=gnu++14 -gdwarf-2 -g3 -Og -o test test.o
test.exe runs as expected. When I profile test.exe, AMD µprof states "The raw file has no data!", whereas VerySleepy does detect activity in sumto and displays the associated source code.
Related
I'm trying to use the JsonCpp library. I'm on Windows, using MinGW and CodeBlocks.
When I include anything from the json headers, my linker implodes and gives out this two errors. I've started to look around and I found these two other questions which basically describe my problem:
problem with g++ and "undefined reference to `__gxx_personality_v0'"
What is __gxx_personality_v0 for?
And if I declare the two missing variables as void pointers, like below, the problem goes away:
void * __gxx_personality_v0=0;
void * _Unwind_Resume =0;
However, I don't understand why this error happens. CodeBlocks is set up so that it uses migw32-g++ for cpp files, and also adding the -lstdc++ option does not fix the problem. Neither does the option -fno-exception ( I want exceptions, mind you, I was just trying ).
I'm also including a boost library in the same file and that does not cause any problems.
EDIT:
The error output is exactly what I said in my title: I get a total of 22 undefined references to _Unwind_Resume and __gxx_personality_v0 during the linking. My code is:
#include <boost/algorithm/string.hpp>
#include <include/json/value.h>
//void * __gxx_personality_v0=0;
//void * _Unwind_Resume =0;
int main () {
std::string str1("Hello world!");
boost::to_upper(str1);
Json::Value k;
return 0;
}
The error is there only when I include/use the JsonCPP library. Uncommenting the commented lines fixes the problem.
The command line output is this:
mingw32-g++.exe -Wall -fexceptions -g -DSFML_DYNAMIC -IC:\Users\Svalorzen\Documents\Projects\boost_1_49 -IC:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0 -IC:\Users\Svalorzen\Documents\Projects\SFML-1.6\include -IC:\Users\Svalorzen\Documents\Projects\hge181\include -c C:\Users\Svalorzen\Documents\Projects\test\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -LC:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0 -LC:\Users\Svalorzen\Documents\Projects\SFML-1.6\lib -LC:\Users\Svalorzen\Documents\Projects\hge181\lib -o bin\Debug\test.exe obj\Debug\main.o -fno-exceptions -lsfml-graphics -lsfml-window -lsfml-system C:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0\libs\mingw\libjson_mingw_libmt.a C:\Users\Svalorzen\Documents\Projects\hge181\lib\gcc\libhge.a C:\Users\Svalorzen\Documents\Projects\hge181\lib\gcc\libhelp.a
Output size is 1.22 MB
Process terminated with status 0 (0 minutes, 3 seconds)
0 errors, 0 warnings
SECOND EDIT:
I'm adding the command lines I use to compile the library:
g++ -o buildscons\mingw\src\lib_json\json_reader.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_reader.cpp
g++ -o buildscons\mingw\src\lib_json\json_value.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_value.cpp
g++ -o buildscons\mingw\src\lib_json\json_writer.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_writer.cpp
ar rc buildscons\mingw\src\lib_json\libjson_mingw_libmt.a buildscons\mingw\src\lib_json\json_reader.o buildscons\mingw\src\lib_json\json_value.o buildscons\mingw\src\lib_json\json_writer.o
ranlib buildscons\mingw\src\lib_json\libjson_mingw_libmt.a
For those coming to this from google (like i did), the real cause of the undefined references to _Unwind_Resume and __gxx_personality_v0 is "using a gcc that uses a different stack unwinding method than dwarf2" [1]
In my case it was attempting to link code compiled with GCC 4.9 upwards with a library compiled with GCC 4.8 or below. The solution is to recompile the library with the same compiler you're building with.
I encountered that same problem attempting to use g++ -g -std=c++17 ... . I removed that option and, once I had removed use of a C++17 feature, it compiled, linked and ran.
I finally fixed this by importing into Code::Blocks the source code of JsonCpp and creating the library myself. I am still baffled though as to why the library created with Scons didn't work, since it was using the same compiler that Code::Blocks uses, but at the same time it was not ( or the error wouldn't have been there ).
There is an interesting article about ARM8.1 Graviton 2 offering of AWS.
This article has tests for CPU coherency where I am trying to repeat.
There is C++ code repo in GitHub named core-latency using Nonius Micro-benchmarking.
I managed to replicate the first test without atomic instructions using the command below to compile:
$ g++ -std=c++11 -Wall -pthread -O3 -Iinclude -o core-latency main.cpp -march=armv8-a
The article claims that ARMv8.1 uses atomic CAS operations and has much better performance. It also provides test results that are much better.
I tried to repeat it compiling with ARMv8.1, ARMv8.2, and ARMv8.3. Sample commands for compilation are below:
$ g++ -std=c++11 -Wall -pthread -O3 -Iinclude -o core-latency main.cpp -march=armv8.1-a+lse
$ g++ -std=c++11 -Wall -pthread -O3 -Iinclude -o core-latency main.cpp -march=armv8.2-a+lse
$ g++ -std=c++11 -Wall -pthread -O3 -Iinclude -o core-latency main.cpp -march=armv8.3-a+lse
None of these improved the performance. Because of that I got the assembly code for it using these commands:
g++ -std=c++11 -Wall -pthread -O3 -Iinclude -S main.cpp -march=armv8.1-a+lse
g++ -std=c++11 -Wall -pthread -O3 -Iinclude -S main.cpp -march=armv8.2-a+lse
g++ -std=c++11 -Wall -pthread -O3 -Iinclude -S main.cpp -march=armv8.3-a+lse
I searched the code and cannot find any CAS operations used.
I also tried the different variations of compilation with or without "lse" and "-moutline-atomics".
I am not a C++ expert and I have a very basic understanding of it.
My guess is that the code needs some changes to use atomic instructions.
Tests are executed on m6g.16xlarge EC2 instance in AWS. OS Ubuntu 20.04.
So if someone can check the core-latency code and give some insights to make sure that it compiles with CAS instructions, that will be a great help.
After doing some more experiments, I found the problem.
In the code snippet below are the steps:
making a comparison first (if state equals Ping)
calling the class method set to do an atomic store operation.
Code snippet from core-latency:
if (state == Ping)
sync.set(Pong);
...
void set(State new_state)
{
state.store(new_state);
}
All of the code never compiles to a CAS instruction. If you want to have an atomic compare and swap operation, you need to use the relevant method from atomic.
I have written below a sample code for experimenting:
#include <atomic>
#include <cstdio>
int main() {
int expected = 0;
int desired = 1;
std::atomic<int> current;
current.store(expected);
printf("Before %d\n", current.load());
while(!current.compare_exchange_weak(expected,desired));
printf("After %d\n", current.load());
}
I compiled it for ARMv8.1 and can see that it is using CAS instruction.
I compiled it for ARMv8.0 and can see that it is not using CAS instruction (which is OK as it is not supported in this version).
So if I want to get CAS instruction sets used, I need to use atomic::compare_exchange_weak or atomic::compare_exchange_strong; otherwise, the compiler will not use CAS but compile your comparison and store operations separately.
In summary, I can rewrite the benchmark with atomic::compare_exchange_weak and see what results I am getting.
New update April 30
I have created the new version of the code with atomic compare and swap support.
It is available here https://github.com/fuatu/core-latency-atomic
Here are the test results for instance m6g.16xlarge (ARM):
Without CAS: Average latency 245ns
With CAS: Average latency 39ns
I'm using GCC version 4.7.2. I create a static library having two files "ctest1.cpp" and "ctest2.cpp".
ctest1.cpp
#include <stdio.h>
#include "ctest2.h"
void ctest1()
{
printf("In ctest1");
ctest2();
}
ctest2.cpp
#include <stdio.h>
void ctest2()
{
printf("In ctest2");
}
The header file "ctest2.h" is,
void ctest2();
And similarly the file "ctest1.h",
void ctest1();
This static library is linked to the following main file "in_test.cpp",
in_test.cpp
#include <stdio.h>
#include "ctest1.h"
using namespace std;
int main()
{
ctest1();
printf("InMain\n");
return 0;
}
I was expecting that after providing proper feedback and enabling -flto, the compiler should have inlined the function call ctest2() in file "ctest1.cpp"(and even call ctest1() in "in_test.cpp"), but it doesn't. Following are the compilation steps that I follow:
g++ -Wall -c -g -O3 -fprofile-generate -ftest-coverage ctest2.cpp ctest1.cpp
ar -rcsv libtest.a ctest2.o ctest1.o
g++ -Wall -g -O3 -fprofile-generate -ftest-coverage in_test.cpp -o checking libtest.a
For training I run the executable n times, then
g++ -Wall -c -g -O3 -flto -fwhole-program -fprofile-use ctest2.cpp ctest1.cpp
ar -rcsv libtest.a ctest2.o ctest1.o
g++ -Wall -g -O3 -flto -fwhole-program -fprofile-use in_test.cpp -o checking libtest.a
I have also tried -fuse-linker-plugin where I gave the path to the gold linker in the compilation command, but the functions were not inlined. I would also like to bring to your notice that when I try this experiment without creation of a static library (with flto and feedback), the compiler inlines the function calls. In that case, I just create one executable out of all the files. This is the reason I was expecting it to work in case of static libraries.
Can someone please tell me what's going wrong here ?
I'm trying to use the JsonCpp library. I'm on Windows, using MinGW and CodeBlocks.
When I include anything from the json headers, my linker implodes and gives out this two errors. I've started to look around and I found these two other questions which basically describe my problem:
problem with g++ and "undefined reference to `__gxx_personality_v0'"
What is __gxx_personality_v0 for?
And if I declare the two missing variables as void pointers, like below, the problem goes away:
void * __gxx_personality_v0=0;
void * _Unwind_Resume =0;
However, I don't understand why this error happens. CodeBlocks is set up so that it uses migw32-g++ for cpp files, and also adding the -lstdc++ option does not fix the problem. Neither does the option -fno-exception ( I want exceptions, mind you, I was just trying ).
I'm also including a boost library in the same file and that does not cause any problems.
EDIT:
The error output is exactly what I said in my title: I get a total of 22 undefined references to _Unwind_Resume and __gxx_personality_v0 during the linking. My code is:
#include <boost/algorithm/string.hpp>
#include <include/json/value.h>
//void * __gxx_personality_v0=0;
//void * _Unwind_Resume =0;
int main () {
std::string str1("Hello world!");
boost::to_upper(str1);
Json::Value k;
return 0;
}
The error is there only when I include/use the JsonCPP library. Uncommenting the commented lines fixes the problem.
The command line output is this:
mingw32-g++.exe -Wall -fexceptions -g -DSFML_DYNAMIC -IC:\Users\Svalorzen\Documents\Projects\boost_1_49 -IC:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0 -IC:\Users\Svalorzen\Documents\Projects\SFML-1.6\include -IC:\Users\Svalorzen\Documents\Projects\hge181\include -c C:\Users\Svalorzen\Documents\Projects\test\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -LC:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0 -LC:\Users\Svalorzen\Documents\Projects\SFML-1.6\lib -LC:\Users\Svalorzen\Documents\Projects\hge181\lib -o bin\Debug\test.exe obj\Debug\main.o -fno-exceptions -lsfml-graphics -lsfml-window -lsfml-system C:\Users\Svalorzen\Documents\Projects\jsoncpp-src-0.5.0\libs\mingw\libjson_mingw_libmt.a C:\Users\Svalorzen\Documents\Projects\hge181\lib\gcc\libhge.a C:\Users\Svalorzen\Documents\Projects\hge181\lib\gcc\libhelp.a
Output size is 1.22 MB
Process terminated with status 0 (0 minutes, 3 seconds)
0 errors, 0 warnings
SECOND EDIT:
I'm adding the command lines I use to compile the library:
g++ -o buildscons\mingw\src\lib_json\json_reader.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_reader.cpp
g++ -o buildscons\mingw\src\lib_json\json_value.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_value.cpp
g++ -o buildscons\mingw\src\lib_json\json_writer.o -c -DWIN32 -DNDEBUG -D_MT -Iinclude src\lib_json\json_writer.cpp
ar rc buildscons\mingw\src\lib_json\libjson_mingw_libmt.a buildscons\mingw\src\lib_json\json_reader.o buildscons\mingw\src\lib_json\json_value.o buildscons\mingw\src\lib_json\json_writer.o
ranlib buildscons\mingw\src\lib_json\libjson_mingw_libmt.a
For those coming to this from google (like i did), the real cause of the undefined references to _Unwind_Resume and __gxx_personality_v0 is "using a gcc that uses a different stack unwinding method than dwarf2" [1]
In my case it was attempting to link code compiled with GCC 4.9 upwards with a library compiled with GCC 4.8 or below. The solution is to recompile the library with the same compiler you're building with.
I encountered that same problem attempting to use g++ -g -std=c++17 ... . I removed that option and, once I had removed use of a C++17 feature, it compiled, linked and ran.
I finally fixed this by importing into Code::Blocks the source code of JsonCpp and creating the library myself. I am still baffled though as to why the library created with Scons didn't work, since it was using the same compiler that Code::Blocks uses, but at the same time it was not ( or the error wouldn't have been there ).
I'm using MinGw on Windows 7. The following simple program compiles fine, but the linker complains and I do not understand what's wrong:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> iv;
iv.push_back(7);
cout << iv.back() << endl;
return 0;
}
the compiler/linker messages look as follows:
mingw32-g++.exe -Wall -fexceptions -std=c++0x -Wall -g -std=c++0x -Wall -g -frepo -IC:\cppbuchincludes\include -IG:\Boost -IG:\Users\thomas\cpp\STLUsage\\include -c G:\Users\thomas\cpp\STLUsage\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -o bin\Debug\STLUsage.exe obj\Debug\main.o G:\Boost\stage\lib\libboost_filesystem-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_regex-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_system-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_thread-mgw45-mt-1_45.dll.a G:\Boost\stage\lib\libboost_unit_test_framework-mgw45-mt-d-1_45.dll.a
collect: recompiling G:\Users\thomas\cpp\STLUsage\main.cpp
collect: relinking
collect2: '_ZNSt12_Vector_baseIiSaIiEEC1Ev' was assigned to 'obj\Debug\main.rpo', but was not defined during recompilation, or vice versa
obj\Debug\main.o: In function `vector':
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_vector.h:208: undefined reference to `std::_Vector_base<int, std::allocator<int> >::_Vector_base()'
(...and so on...)
I can use templates I defined myself.
I have that MinGw binary from a book and followed the instructions in that book regarding compiler settings. In particular the references to the Boost libs are taken from there.
This must be a simple thing, I just want to make trivial use of the STL.
Edit following the advice given in an answer, I replaced the binary to be used to compile by g++.exe in the Settings -> Compiler and debugging -> toolchain executables dialog, but I'm getting the same error messages (with mingw32-g++.exe now replaced by g++.exe).
Edit (once more) this has to be problem eith the Code::Blocks settings, since compiling using g++ from the command line works just fine.
Use g++ to compile and link the program. mingw32-g++.exe doesn't do that.
FAQ says,
What's the difference between gcc and mingw32-gcc?
The mingw32-gcc, mingw32-g++, etc. binaries exist as an aid to cross development. They are created in a typical build of gcc. They are therefore distributed as the maintainers of GCC meant them to be. The gcc.exe indicates that the binary produces binaries for a target equal to the build, while the mingw32-gcc binary produces binaries to be executed on the mingw32 target.
So I guess the problem is because of mingw32-g++.exe which you're not supposed to use, for normal build.
Try these:
g++ program.cpp //simple build
g++ program.cpp -Wall //build with all warnings enabled
g++ program.cpp -Wall -O2 //enable warnings and optimization level 2
g++ program.cpp -std=c++0x //use C++11 features
Hope that helps.