{"id":13418041,"url":"https://github.com/yse/easy_profiler","last_synced_at":"2025-05-14T04:07:31.596Z","repository":{"id":38706788,"uuid":"51919490","full_name":"yse/easy_profiler","owner":"yse","description":"Lightweight profiler library for c++","archived":false,"fork":false,"pushed_at":"2024-11-30T10:15:20.000Z","size":3258,"stargazers_count":2272,"open_issues_count":88,"forks_count":196,"subscribers_count":74,"default_branch":"develop","last_synced_at":"2025-05-06T07:27:01.934Z","etag":null,"topics":["performance","profiler","toolkit"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["yse","cas4ey"],"open_collective":"easy_profiler","custom":["https://paypal.me/ysergey"]}},"created_at":"2016-02-17T12:01:15.000Z","updated_at":"2025-05-05T12:17:45.000Z","dependencies_parsed_at":"2024-04-04T20:31:46.237Z","dependency_job_id":"c0e4f6ea-238b-40e3-a9cf-65af78465083","html_url":"https://github.com/yse/easy_profiler","commit_stats":{"total_commits":907,"total_committers":29,"mean_commits":"31.275862068965516","dds":0.442116868798236,"last_synced_commit":"2f22059a40cc92f9f27ca4c88af0299882f8c129"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yse%2Feasy_profiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yse%2Feasy_profiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yse%2Feasy_profiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yse%2Feasy_profiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yse","download_url":"https://codeload.github.com/yse/easy_profiler/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069206,"owners_count":22009506,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["performance","profiler","toolkit"],"created_at":"2024-07-30T22:00:57.754Z","updated_at":"2025-05-14T04:07:31.557Z","avatar_url":"https://github.com/yse.png","language":"C++","readme":"# easy_profiler [![2.1.0](https://img.shields.io/badge/stable-2.1.0-009688.svg)](https://github.com/yse/easy_profiler/releases/tag/v2.1.0) [![3.x.x](https://img.shields.io/badge/latest-3.x.x-f57f17.svg)](https://github.com/yse/easy_profiler)\n\n[![Build Status](https://ci.appveyor.com/api/projects/status/github/yse/easy_profiler?branch=develop\u0026svg=true)](https://ci.appveyor.com/project/yse/easy-profiler/branch/develop)\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\n1. [About](#about)\n2. [Key features](#key-features)\n3. [Usage](#usage)\n    - [Integration](#integration)\n       - [General build system](#general)\n       - [CMake](#if-using-cmake)\n    - [Inserting blocks](#inserting-blocks)\n    - [Storing variables](#storing-variables)\n    - [Collect profiling data](#collect-profiling-data)\n        - [Streaming over network](#streaming-over-network)\n        - [Dump to file](#dump-to-file)\n        - [Note about thread context-switch events](#note-about-thread-context-switch-events)\n        - [Profiling application startup](#profiling-application-startup)\n4. [Build](#build)\n    - [Linux](#linux)\n    - [MacOS](#macos)\n    - [Windows](#windows)\n    - [QNX](#qnx)\n    - [Android](#android)\n5. [Notes about major release 1.x -\u003e 2.x and 2.x -\u003e 3.x](#status)\n6. [License](#license)\n\n# About\nLightweight cross-platform profiler library for c++\n\nYou can profile any function in you code. Furthermore this library provide measuring time of any block of code.\nFor example, information for 12 millions of blocks is using less than 300Mb of memory.\nWorking profiler slows your application execution for only 1-2%.\n\n![Block time](https://hsto.org/files/3e4/afe/8b7/3e4afe8b77ac4ad3a6f8c805be4b7f13.png)\n_Average overhead per block is about 15ns/block (tested on Intel Core i7-5930K 3.5GHz, Win7)_\n\nDisabled profiler will not affect your application execution in any way. You can leave it in your Release build\nand enable it at run-time at any moment during application launch to see what is happening at the moment.\n\nAlso the library can capture system's context switch events between threads. Context switch information includes\nduration, target thread id, thread owner process id, thread owner process name.\n\nYou can see the results of measuring in simple GUI application which provides full statistics and renders beautiful time-line.\n\n![GUI screenshot](https://cloud.githubusercontent.com/assets/1775230/24852044/a0b1edd0-1dde-11e7-8736-7052b840ad06.png)\n_Profiling CryEngine SDK example_\n\n![New UI Style](https://user-images.githubusercontent.com/10530007/40890463-0ab378f8-677f-11e8-9b10-9c62ffb7d5b8.png)\n_New UI style in version 2.0_\n\n# Key features\n\n- Extremely low overhead\n- Low additional memory usage\n- Cross-platform\n- Profiling over network\n- Capture thread context-switch events\n- Store user variables (both single values and arrays)\n- GUI could be connected to an application which is already profiling (so you can profile initialization of your application)\n- Monitor main thread fps at real-time in GUI even if profiling is disabled or draw your own HUD/fps-plot directly in your application using data provided by profiler\n- Save a snapshot (selected area) of profiled data from file\n- Add bookmarks at any place on the timeline\n- Configurable timer type with CMakeLists or preprocessor macros \n\n# Usage\n\n## Integration\n\n### General\n\nFirst of all you can specify path to include directory which contains `include/profiler` directory and define macro `BUILD_WITH_EASY_PROFILER`.\nFor linking with easy_profiler you can specify path to library.\n\n### If using CMake\n\nIf you are using `cmake` set `CMAKE_PREFIX_PATH` to `lib/cmake/easy_profiler` directory (from [release](https://github.com/yse/easy_profiler/releases) package) and use function `find_package(easy_profiler)` with `target_link_libraries(... easy_profiler)`. \n\nExample:\n``` cmake\nproject(my_application)\n\nset(SOURCES\n    main.cpp\n)\n\n# CMAKE_PREFIX_PATH should be set to \u003ceasy_profiler-release_dir\u003e/lib/cmake/easy_profiler\nfind_package(easy_profiler REQUIRED)  # STEP 1 #########################\n\nadd_executable(my_application ${SOURCES})\n\ntarget_link_libraries(my_application easy_profiler)  # STEP 2 ##########\n```\n\n## Inserting blocks\n\nExample of usage.\n\n```cpp\n#include \u003ceasy/profiler.h\u003e\n\nvoid foo() {\n    EASY_FUNCTION(profiler::colors::Magenta); // Magenta block with name \"foo\"\n\n    EASY_BLOCK(\"Calculating sum\"); // Begin block with default color == Amber100\n    int sum = 0;\n    for (int i = 0; i \u003c 10; ++i) {\n        EASY_BLOCK(\"Addition\", profiler::colors::Red); // Scoped red block (no EASY_END_BLOCK needed)\n        sum += i;\n    }\n    EASY_END_BLOCK; // End of \"Calculating sum\" block\n\n    EASY_BLOCK(\"Calculating multiplication\", profiler::colors::Blue500); // Blue block\n    int mul = 1;\n    for (int i = 1; i \u003c 11; ++i)\n        mul *= i;\n    //EASY_END_BLOCK; // This is not needed because all blocks are ended on destructor when closing braces met\n}\n\nvoid bar() {\n    EASY_FUNCTION(0xfff080aa); // Function block with custom ARGB color\n}\n\nvoid baz() {\n    EASY_FUNCTION(); // Function block with default color == Amber100\n}\n```\n\nEasyProfiler is using Google Material-Design colors palette, but you can use custom colors in ARGB format (like shown in example above).  \nThe default color is `Amber100` (it is used when you do not specify color explicitly). \n\n## Storing variables\n\nExample of storing variables:\n```cpp\n#include \u003ceasy/profiler.h\u003e\n#include \u003ceasy/arbitrary_value.h\u003e // EASY_VALUE, EASY_ARRAY are defined here\n\nclass Object {\n    Vector3 m_position; // Let's suppose Vector3 is a struct { float x, y, z; };\n    unsigned int  m_id;\npublic:\n    void act() {\n        EASY_FUNCTION(profiler::colors::Cyan);\n\n        // Dump variables values\n        constexpr auto Size = sizeof(Vector3) / sizeof(float);\n        EASY_VALUE(\"id\", m_id);\n        EASY_ARRAY(\"position\", \u0026m_position.x, Size, profiler::color::Red);\n\n        // Do something ...\n    }\n\n    void loop(uint32_t N) {\n        EASY_FUNCTION();\n        EASY_VALUE(\"N\", N, EASY_VIN(\"N\")); /* EASY_VIN is used here to ensure\n                                            that this value id will always be\n                                            the same, because the address of N\n                                            can change */\n        for (uint32_t i = 0; i \u003c N; ++i) {\n            // Do something\n        }\n    }\n};\n```\n\n## Collect profiling data\n\nThere are two ways to collect profiling data: streaming over network and dumping data to file.\n\n### Streaming over network\n\nThis is the most preferred and convenient method in many cases.\n\n1. (In profiled app) Invoke `profiler::startListen()`. This will start new thread to listen `28077` port for the start-capture-signal from profiler_gui.\n2. (In UI) Connect profiler_gui to your application using `hostname` or `IP-address`.\n3. (In UI) Press `Start capture` button in profiler_gui.\n4. (In UI) Press `Stop capture` button in profiler_gui to stop capturing and wait until profiled data will be passed over network.\n5. (Optional step)(In profiled app) Invoke `profiler::stopListen()` to stop listening. \n\nExample:\n```cpp\nvoid main() {\n    profiler::startListen();\n    /* do work */\n}\n```\n\n### Dump to file\n\n1. (Profiled application) Start capturing by putting `EASY_PROFILER_ENABLE` macro somewhere into the code.\n2. (Profiled application) Dump profiled data to file in any place you want by `profiler::dumpBlocksToFile(\"test_profile.prof\")` function.\n\nExample:\n```cpp\nvoid main() {\n    EASY_PROFILER_ENABLE;\n    /* do work */\n    profiler::dumpBlocksToFile(\"test_profile.prof\");\n}\n```\n\n### Note about thread context-switch events\n\nTo capture a thread context-switch events you need:\n\n- On Windows: launch your application \"as Administrator\"\n- On Linux: you can launch special `systemtap` script with root privileges as follow (example on Fedora):\n```bash\n#stap -o /tmp/cs_profiling_info.log scripts/context_switch_logger.stp name APPLICATION_NAME\n```\nAPPLICATION_NAME - name of your application\n\nThere are some known issues on a linux based systems (for more information see [wiki](https://github.com/yse/easy_profiler/wiki/Known-bugs-and-issues))\n\n### Profiling application startup\n\nTo profile your application startup (when using [network](#streaming-over-network) method) add `EASY_PROFILER_ENABLE` macro into the code together with `profiler::startListen()`. \n\nExample:\n```cpp\nvoid main() {\n    EASY_PROFILER_ENABLE;\n    profiler::startListen();\n    /* do work */\n}\n```\n\nThis will allow you to collect profiling data before profiler_gui connection. profiler_gui will automatically display capturing dialog window after successful connection to the profiled application. \n\n# Build\n\n## Prerequisites\n\n* CMake 3.0 or higher\n* Compiler with c++11 support\n  * for Unix systems: compiler with `thread_local` support is **highly recommended**: _GCC \u003e=4.8_, _Clang \u003e=3.3_\n\nAdditional requirements for GUI:\n* Qt 5.3.0 or higher\n\n## Linux\n\n```bash\n$ mkdir build\n$ cd build\n$ cmake -DCMAKE_BUILD_TYPE=\"Release\" ..\n$ make\n```\n\n## MacOS\n\n```bash\n$ mkdir build\n$ cd build\n$ cmake -DCMAKE_CXX_COMPILER=g++-5 -DCMAKE_C_COMPILER=gcc-5 -DCMAKE_BUILD_TYPE=\"Release\" ..\n$ make\n```\n\n## Windows\n\nIf you are using QtCreator IDE you can just open `CMakeLists.txt` file in root directory.\nIf you are using Visual Studio you can generate solution by cmake generator command.\nExamples shows how to generate Win64 solution for Visual Studio 2013. To generate for another version use proper cmake generator (-G \"name of generator\").\n\n### Way 1\nSpecify path to cmake scripts in Qt6 dir (usually in lib/cmake subdir) and execute cmake generator command,\nfor example:\n```batch\n$ mkdir build\n$ cd build\n$ cmake -DCMAKE_PREFIX_PATH=\"C:\\Qt\\6.7.2\\msvc2013_64\\lib\\cmake\" .. -G \"Visual Studio 12 2013 Win64\"\n```\n\n### Way 2\nCreate system variable \"Qt6Widgets_DIR\" and set it's value to \"[path-to-Qt6-binaries]\\lib\\cmake\\Qt6Widgets\".\nFor example, \"C:\\Qt\\5.3\\msvc2013_64\\lib\\cmake\\Qt6Widgets\".\nAnd then run cmake generator as follows:\n```batch\n$ mkdir build\n$ cd build\n$ cmake .. -G \"Visual Studio 12 2013 Win64\"\n```\n\n## QNX\n```bash\n$ souce $QNX_ENVIRONMENT\n$ mkdir build\n$ cd build\n$ cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/QNXToolchain.cmake ..\n```\nFor more information and example for `QNXToolchain.cmake` see [this PR](https://github.com/yse/easy_profiler/pull/145) \n\n## Android\n\nYou can build native library for android by using NDK and standalone toolchain. See [comment for this PR](https://github.com/yse/easy_profiler/pull/137#issuecomment-436167127) to get a more detailed instruction.\n\n# Status\n## Migration 1.x --\u003e 2.x\nBranch `develop` contains all v2.0.0 features and new UI style.  \nPlease, note that .prof file header has changed in v2.0.0:\n```cpp\nstruct EasyFileHeader {\n    uint32_t signature = 0;\n    uint32_t version = 0;\n    profiler::processid_t pid = 0;\n    int64_t cpu_frequency = 0;\n    profiler::timestamp_t begin_time = 0;\n    profiler::timestamp_t end_time = 0;\n    \n    // Changed order of memory_size and blocks_number relative to v1.3.0\n    uint64_t memory_size = 0;\n    uint64_t descriptors_memory_size = 0;\n    uint32_t total_blocks_number = 0;\n    uint32_t total_descriptors_number = 0;\n};\n```\n\n## Migration 2.x --\u003e 3.x\n\nThere are some functions in the 2.x release that conflicts with system functions, for example `now()`. You can find more details in the related [issue](https://github.com/yse/easy_profiler/issues/215) and [PR](https://github.com/yse/easy_profiler/pull/188)\n\n# License\n\nLicensed under either of\n- MIT license ([mit.lic](mit.lic) or http://opensource.org/licenses/MIT)\n- Apache License, Version 2.0 ([apache.lic](apache.lic) or http://www.apache.org/licenses/LICENSE-2.0)\n\nat your option.\n","funding_links":["https://github.com/sponsors/yse","https://github.com/sponsors/cas4ey","https://opencollective.com/easy_profiler","https://paypal.me/ysergey"],"categories":["TODO scan for Android support in followings","Libraries","C++","Profiling"],"sub_categories":["Benchmark / Profile","fake data"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyse%2Feasy_profiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyse%2Feasy_profiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyse%2Feasy_profiler/lists"}