mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-28 01:04:41 +08:00
Merge branch 'develop' of https://github.com/yse/easy_profiler into develop
This commit is contained in:
commit
46a9caddb8
97
README.md
97
README.md
@ -1,14 +1,13 @@
|
||||
# easy_profiler [![License](https://img.shields.io/badge/license-GPL3-blue.svg)](https://github.com/yse/easy_profiler/blob/develop/COPYING)[![Build Status](https://travis-ci.org/yse/easy_profiler.svg?branch=develop)](https://travis-ci.org/yse/easy_profiler)
|
||||
|
||||
1. [About](#about)
|
||||
2. [Build](#build)
|
||||
2. [Usage](#usage)
|
||||
3. [Build](#build)
|
||||
- [Linux](#linux)
|
||||
- [Windows](#windows)
|
||||
3. [Usage](#usage)
|
||||
|
||||
|
||||
# About
|
||||
Lightweight profiler library for c++
|
||||
Lightweight cross-platform profiler library for c++
|
||||
|
||||
You can profile any function in you code. Furthermore this library provide measuring time of any block of code.
|
||||
For example, information for 12 millions of blocks is using less than 300Mb of memory.
|
||||
@ -22,50 +21,6 @@ duration, target thread id, thread owner process id, thread owner process name.
|
||||
|
||||
You can see the results of measuring in simple GUI application which provides full statistics and renders beautiful time-line.
|
||||
|
||||
# Build
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For core:
|
||||
* compiler with c++11 support
|
||||
* cmake 3.0 or later
|
||||
|
||||
For GUI:
|
||||
* Qt 5.3.0 or later
|
||||
|
||||
## Linux
|
||||
|
||||
```bash
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
If you are using QtCreator IDE you can just open `CMakeLists.txt` file in root directory.
|
||||
If you are using Visual Studio you can generate solution by cmake generator command.
|
||||
|
||||
### Way 1
|
||||
Specify path to cmake scripts in Qt5 dir (usually in lib/cmake subdir) and execute cmake generator command,
|
||||
for example:
|
||||
```batch
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake -DCMAKE_PREFIX_PATH="C:\Qt\5.3\msvc2013_64\lib\cmake" .. -G "Visual Studio 12 2013 Win64"
|
||||
```
|
||||
|
||||
### Way 2
|
||||
Create system variable "Qt5Widgets_DIR" and set it's value to "[path-to-Qt5-binaries]\lib\cmake\Qt5Widgets".
|
||||
For example, "C:\Qt\5.3\msvc2013_64\lib\cmake\Qt5Widgets".
|
||||
And then run cmake generator as follows:
|
||||
```batch
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake .. -G "Visual Studio 12 2013 Win64"
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
First of all you can specify path to include directory which contains `include/profiler` directory.
|
||||
@ -117,4 +72,50 @@ void foo() {
|
||||
}
|
||||
```
|
||||
|
||||
# Build
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For core:
|
||||
* compiler with c++11 support
|
||||
* cmake 3.0 or later
|
||||
|
||||
For GUI:
|
||||
* Qt 5.3.0 or later
|
||||
|
||||
## Linux
|
||||
|
||||
```bash
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
If you are using QtCreator IDE you can just open `CMakeLists.txt` file in root directory.
|
||||
If you are using Visual Studio you can generate solution by cmake generator command.
|
||||
|
||||
### Way 1
|
||||
Specify path to cmake scripts in Qt5 dir (usually in lib/cmake subdir) and execute cmake generator command,
|
||||
for example:
|
||||
```batch
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake -DCMAKE_PREFIX_PATH="C:\Qt\5.3\msvc2013_64\lib\cmake" .. -G "Visual Studio 12 2013 Win64"
|
||||
```
|
||||
|
||||
### Way 2
|
||||
Create system variable "Qt5Widgets_DIR" and set it's value to "[path-to-Qt5-binaries]\lib\cmake\Qt5Widgets".
|
||||
For example, "C:\Qt\5.3\msvc2013_64\lib\cmake\Qt5Widgets".
|
||||
And then run cmake generator as follows:
|
||||
```batch
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake .. -G "Visual Studio 12 2013 Win64"
|
||||
```
|
||||
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-82899176-1/easy_profiler/readme)](https://github.com/yse/easy_profiler)
|
||||
|
@ -3,7 +3,7 @@
|
||||
unamestr=`uname`
|
||||
SUBDIR="./bin"
|
||||
if [[ ! "$unamestr" == 'Linux' ]]; then
|
||||
SUBDIR="./bin/Release/"
|
||||
SUBDIR="./bin/Release/"
|
||||
fi
|
||||
|
||||
DISABLED_PROF=$SUBDIR/profiler_sample_disabled_profiler
|
||||
@ -12,31 +12,46 @@ ENABLED_PROF=$SUBDIR/profiler_sample
|
||||
TEMP_FILE_ENABLE="enable.info"
|
||||
TEMP_FILE_DISABLE="disable.info"
|
||||
RESULT_FILE="result.csv"
|
||||
RESULT_FILE_TMP="result.csv.tmp"
|
||||
|
||||
echo "Blocks count, dT prof enabled usec, dT prof disabled usec" > $RESULT_FILE
|
||||
HEADER="Blocks count, dT prof enabled usec, dT prof disabled usec,delta, usec/block"
|
||||
|
||||
#echo "Blocks count, dT prof enabled usec, dT prof disabled usec,delta, usec/block" > $RESULT_FILE
|
||||
|
||||
rm -rf $RESULT_FILE
|
||||
|
||||
for i in {1..9}
|
||||
do
|
||||
OBJECTS_COUNT=$(($i*100))
|
||||
for j in {10..15}
|
||||
do
|
||||
RENDER_COUNT=$(($j*100))
|
||||
for k in {10..15}
|
||||
do
|
||||
MODELLING_COUNT=$(($k*100))
|
||||
$ENABLED_PROF $OBJECTS_COUNT $RENDER_COUNT $MODELLING_COUNT > $TEMP_FILE_ENABLE
|
||||
$DISABLED_PROF $OBJECTS_COUNT $RENDER_COUNT $MODELLING_COUNT > $TEMP_FILE_DISABLE
|
||||
DT_ENA=`cat $TEMP_FILE_ENABLE | grep Elapsed| awk '{print $3}'`
|
||||
N_ENA=`cat $TEMP_FILE_ENABLE | grep Blocks| awk '{print $3}'`
|
||||
N_DIS=`cat $TEMP_FILE_DISABLE | grep Elapsed| awk '{print $3}'`
|
||||
echo $N_ENA,$DT_ENA,$N_DIS >> $RESULT_FILE
|
||||
done
|
||||
done
|
||||
OBJECTS_COUNT=$(($i*100))
|
||||
for j in {10..15}
|
||||
do
|
||||
RENDER_COUNT=$(($j*100))
|
||||
for k in {10..15}
|
||||
do
|
||||
MODELLING_COUNT=$(($k*100))
|
||||
$ENABLED_PROF $OBJECTS_COUNT $RENDER_COUNT $MODELLING_COUNT > $TEMP_FILE_ENABLE
|
||||
$DISABLED_PROF $OBJECTS_COUNT $RENDER_COUNT $MODELLING_COUNT > $TEMP_FILE_DISABLE
|
||||
DT_ENA=`cat $TEMP_FILE_ENABLE | grep Elapsed| awk '{print $3}'`
|
||||
N_ENA=`cat $TEMP_FILE_ENABLE | grep Blocks| awk '{print $3}'`
|
||||
N_DIS=`cat $TEMP_FILE_DISABLE | grep Elapsed| awk '{print $3}'`
|
||||
|
||||
DELTA=$(($DT_ENA-$N_DIS))
|
||||
USEC_BLOCK=`awk "BEGIN{print $DELTA/$N_ENA}"`
|
||||
|
||||
echo $N_ENA,$DT_ENA,$N_DIS,$DELTA,$USEC_BLOCK >> $RESULT_FILE
|
||||
done
|
||||
done
|
||||
echo $i
|
||||
|
||||
done
|
||||
|
||||
cat $RESULT_FILE | sort > $RESULT_FILE_TMP
|
||||
|
||||
echo $HEADER > $RESULT_FILE
|
||||
cat $RESULT_FILE_TMP >> $RESULT_FILE
|
||||
|
||||
rm -rf $TEMP_FILE_ENABLE
|
||||
rm -rf $TEMP_FILE_DISABLE
|
||||
rm -rf $RESULT_FILE_TMP
|
||||
|
||||
echo "See result in $RESULT_FILE"
|
||||
|
@ -16,6 +16,7 @@ set(H_FILES
|
||||
profile_manager.h
|
||||
spin_lock.h
|
||||
event_trace_win.h
|
||||
current_time.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -25,6 +25,7 @@
|
||||
************************************************************************/
|
||||
|
||||
#include "profile_manager.h"
|
||||
#include "current_time.h"
|
||||
|
||||
using namespace profiler;
|
||||
|
||||
|
62
src/current_time.h
Normal file
62
src/current_time.h
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016 Sergey Yagovtsev, Victor Zarubkin
|
||||
|
||||
This program is free software : you can redistribute it and / or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program.If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef EASY_______CURRENT_TIME_H_____
|
||||
#define EASY_______CURRENT_TIME_H_____
|
||||
|
||||
#include "profiler/profiler.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <chrono>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static inline profiler::timestamp_t getCurrentTime()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
//see https://msdn.microsoft.com/library/windows/desktop/dn553408(v=vs.85).aspx
|
||||
LARGE_INTEGER elapsedMicroseconds;
|
||||
if (!QueryPerformanceCounter(&elapsedMicroseconds))
|
||||
return 0;
|
||||
return (profiler::timestamp_t)elapsedMicroseconds.QuadPart;
|
||||
#else
|
||||
|
||||
#if (defined(__GNUC__) || defined(__ICC))
|
||||
|
||||
#if defined(__i386__)
|
||||
unsigned long long t;
|
||||
__asm__ __volatile__("rdtsc" : "=A"(t));
|
||||
return t;
|
||||
#elif defined(__x86_64__)
|
||||
unsigned int hi, lo;
|
||||
__asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
return ((uint64_t)hi << 32) | lo;
|
||||
#endif
|
||||
|
||||
#else
|
||||
return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
||||
#define USE_STD_CHRONO
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif // EASY_______CURRENT_TIME_H_____
|
@ -31,6 +31,7 @@
|
||||
#include "profiler/easy_net.h"
|
||||
#include "profiler/easy_socket.h"
|
||||
#include "event_trace_win.h"
|
||||
#include "current_time.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -556,7 +557,36 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
#ifdef _WIN32
|
||||
_outputStream.write(CPU_FREQUENCY);
|
||||
#else
|
||||
|
||||
#if !defined(USE_STD_CHRONO)
|
||||
double g_TicksPerNanoSec;
|
||||
struct timespec begints, endts;
|
||||
uint64_t begin = 0, end = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &begints);
|
||||
begin = getCurrentTime();
|
||||
volatile uint64_t i;
|
||||
for (i = 0; i < 100000000; i++); /* must be CPU intensive */
|
||||
end = getCurrentTime();
|
||||
clock_gettime(CLOCK_MONOTONIC, &endts);
|
||||
struct timespec tmpts;
|
||||
const int NANO_SECONDS_IN_SEC = 1000000000;
|
||||
tmpts.tv_sec = endts.tv_sec - begints.tv_sec;
|
||||
tmpts.tv_nsec = endts.tv_nsec - begints.tv_nsec;
|
||||
if (tmpts.tv_nsec < 0) {
|
||||
tmpts.tv_sec--;
|
||||
tmpts.tv_nsec += NANO_SECONDS_IN_SEC;
|
||||
}
|
||||
|
||||
uint64_t nsecElapsed = tmpts.tv_sec * 1000000000LL + tmpts.tv_nsec;
|
||||
g_TicksPerNanoSec = (double)(end - begin)/(double)nsecElapsed;
|
||||
|
||||
|
||||
|
||||
int64_t cpu_frequency = int(g_TicksPerNanoSec*1000000);
|
||||
_outputStream.write(cpu_frequency*1000LL);
|
||||
#else
|
||||
_outputStream.write(0LL);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Write begin and end time
|
||||
|
@ -40,6 +40,7 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <chrono>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
inline uint32_t getCurrentThreadId()
|
||||
@ -53,20 +54,6 @@ inline uint32_t getCurrentThreadId()
|
||||
#endif
|
||||
}
|
||||
|
||||
inline profiler::timestamp_t getCurrentTime()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
//see https://msdn.microsoft.com/library/windows/desktop/dn553408(v=vs.85).aspx
|
||||
LARGE_INTEGER elapsedMicroseconds;
|
||||
if (!QueryPerformanceCounter(&elapsedMicroseconds))
|
||||
return 0;
|
||||
return (profiler::timestamp_t)elapsedMicroseconds.QuadPart;
|
||||
#else
|
||||
//std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> time_point;
|
||||
return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace profiler {
|
||||
|
||||
class SerializedBlock;
|
||||
|
Loading…
x
Reference in New Issue
Block a user