0
0
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:
Victor Zarubkin 2016-09-26 23:52:05 +03:00
commit 46a9caddb8
7 changed files with 176 additions and 79 deletions

View File

@ -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)

View File

@ -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"

View File

@ -16,6 +16,7 @@ set(H_FILES
profile_manager.h
spin_lock.h
event_trace_win.h
current_time.h
)
set(SOURCES

View File

@ -25,6 +25,7 @@
************************************************************************/
#include "profile_manager.h"
#include "current_time.h"
using namespace profiler;

62
src/current_time.h Normal file
View 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_____

View File

@ -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

View File

@ -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;