{"id":13440905,"url":"https://github.com/dfeneyrou/palanteer","last_synced_at":"2025-05-13T21:08:48.085Z","repository":{"id":38336797,"uuid":"378388977","full_name":"dfeneyrou/palanteer","owner":"dfeneyrou","description":"Visual Python and C++ nanosecond profiler, logger, tests enabler","archived":false,"fork":false,"pushed_at":"2025-03-25T21:40:01.000Z","size":10073,"stargazers_count":2134,"open_issues_count":4,"forks_count":91,"subscribers_count":54,"default_branch":"main","last_synced_at":"2025-04-28T14:07:36.329Z","etag":null,"topics":["c-plus-plus","cpp","developer-tools","embedded","header-only","logging","memory-profiler","optimization","performance","profiler","profiling","python"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dfeneyrou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2021-06-19T10:51:29.000Z","updated_at":"2025-04-28T12:44:53.000Z","dependencies_parsed_at":"2024-11-26T10:04:19.105Z","dependency_job_id":"ef0ff1e3-921c-42f3-bcb9-627092ad0a94","html_url":"https://github.com/dfeneyrou/palanteer","commit_stats":{"total_commits":179,"total_committers":9,"mean_commits":19.88888888888889,"dds":0.1005586592178771,"last_synced_commit":"a53a58ee54b0699538ca21ea0a00c59e22d53229"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfeneyrou%2Fpalanteer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfeneyrou%2Fpalanteer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfeneyrou%2Fpalanteer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfeneyrou%2Fpalanteer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dfeneyrou","download_url":"https://codeload.github.com/dfeneyrou/palanteer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251326840,"owners_count":21571635,"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":["c-plus-plus","cpp","developer-tools","embedded","header-only","logging","memory-profiler","optimization","performance","profiler","profiling","python"],"created_at":"2024-07-31T03:01:27.712Z","updated_at":"2025-04-28T14:07:42.327Z","avatar_url":"https://github.com/dfeneyrou.png","language":"C++","funding_links":[],"categories":["C++","Software","Game-BenchMark/Metric/Tool","Python specific","Project"],"sub_categories":["Trends","Program Analysis"],"readme":"# Look into Palanteer and get an omniscient view of your program\n\n[![Build Status](https://github.com/dfeneyrou/palanteer/workflows/build/badge.svg)](https://github.com/dfeneyrou/palanteer/actions?workflow=build)\n\nPalanteer is a set of lean and efficient tools to improve the quality of software, for C++ and Python programs.\n\n\u003cimg src=\"docs/images/views.gif \" alt=\"Palanteer viewer image\" width=\"1000\"/\u003e\n\nSimple code instrumentation, mostly automatic in Python, delivers powerful features:\n  - **Collection of meaningful atomic events** on timings, memory, locks wait and usage, context switches, data values..\n  - **Efficient logging** with a printf-compatible interface\n  - **Visual and interactive observation** of records: hierarchical logs, timeline, plot, histogram, flame graph...\n  - **Remote command call and events observation can be scripted in Python**: deep testing has never been simpler\n  - **C++**:\n    - ultralight single-header cross-platform instrumentation library\n    - [printf-like nanosecond logging](https://dfeneyrou.github.io/palanteer/index.html#easyandefficientlogging) with level, category and graphable arguments\n    - compile time selection of [groups of instrumentation](https://dfeneyrou.github.io/palanteer/base_concepts.md.html#c++specific/groups)\n    - compile-time hashing of [static strings](https://dfeneyrou.github.io/palanteer/base_concepts.md.html#staticanddynamicstrings) to minimize their cost\n    - compile-time striping of [all instrumentation static strings](https://dfeneyrou.github.io/palanteer/getting_started.md.html#quickc++externalstringconfiguration)\n    - [enhanced assertions](https://dfeneyrou.github.io/palanteer/index.html#enhancedassertions), stack trace dump...\n    - [automatic code instrumentation](https://dfeneyrou.github.io/palanteer/getting_started.md.html#quickc++automaticfunctionsinstrumentation) (Linux GCC only)\n  - **Python**:\n    - [Automatic instrumentation](https://dfeneyrou.github.io/palanteer/instrumentation_api_python.md.html#automaticinstrumentationwithoutcodemodification) of functions enter/leave, memory allocations, raised exceptions, garbage collection runs\n    - Seamless support of multithreading, asyncio/gevent\n\nRecording simultaneously [up to 8 streams](https://dfeneyrou.github.io/palanteer/index.html#multistream) (i.e., from different processes) is supported.\n\nPalanteer is an efficient, lean and comprehensive solution for better and enjoyable software development!\n\n## C++ instrumentation example\n\nBelow is a simple example of a C++ program instrumented with Palanteer and generating 100 000 random integers.\nThe range can be remotely configured with a user-defined CLI.\n\nThe Python scripting module can control this program, in particular:\n   - call the setBoundsCliHandler to change the configuration\n   - temporarily stop the program at the freeze point\n   - see all \"random data\" values and the timing of the scope event \"Generate some random values\"\n\n\u003cdetails\u003e\n  \u003csummary\u003e See C++ example code \u003c/summary\u003e\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++\n// File: example.cpp\n// On Linux, build with:  g++ -DUSE_PL=1 -I \u003cpalanteer C++ instrumentation folder\u003e example.cpp -lpthread -o example\n#include \u003cstdlib.h\u003e          // For \"rand\"\n#define PL_IMPLEMENTATION 1  // The instrumentation library shall be \"implemented\" once\n#include \"palanteer.h\"\n\nint globalMinValue = 0, globalMaxValue = 10;\n\n// Handler (=user implementation) of the example CLI, which sets the range\nvoid setBoundsCliHandler(plCliIo\u0026 cio)             // 'cio' is a communication helper passed to each C++ CLI handler\n{\n    int minValue = cio.getParamInt(0);             // Get the 2 CLI parameters as integers (as declared)\n    int maxValue = cio.getParamInt(1);\n    if(minValue\u003emaxValue) {                        // Case where the CLI execution fails. The text answer contains some information about it\n        cio.setErrorState(\"Minimum value (%d) shall be lower than the maximum value (%d)\", minValue, maxValue);\n        return;\n    }\n\n    // Modify the state of the program. No care about thread-safety here, to keep the example simple\n    globalMinValue = minValue;\n    globalMaxValue = maxValue;\n    // CLI execution was successful (because no call to cio.setErrorState())\n}\n\n\nint main(int argc, char** argv)\n{\n    plInitAndStart(\"example\");              // Start the instrumentation, for the program named \"example\"\n    plDeclareThread(\"Main\");                // Declare the current thread as \"Main\" so that it can be identified more easily in the script\n    plRegisterCli(setBoundsCliHandler, \"config:setRange\", \"min=int max=int\", \"Sets the value bounds of the random generator\");  // Declare our CLI\n    plFreezePoint();                        // Add a freeze point here to be able to configure the program at a controlled moment\n\n    plBegin(\"Generate some random values\");\n    for(int i=0; i\u003c100000; ++i) {\n        int value = globalMinValue + rand()%(globalMaxValue+1-globalMinValue);\n        plData(\"random data\", value);       // Here are the \"useful\" values\n    }\n    plEnd(\"\");                              // Shortcut for plEnd(\"Generate some random values\")\n\n    plStopAndUninit();                      // Stop and uninitialize the instrumentation\n    return 0;\n}\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\u003c/details\u003e\n\nSome C++ performance figures (see [here](https://dfeneyrou.github.io/palanteer/index.html#performance) for more details):\n  - nanosecond resolution and ~25 nanoseconds cost per event on a standard x64 machine\n  - up to ~5 millions events per second when recording, bottleneck on the server processing side\n  - up to ~150 000 events per second when processing the flow through a Python script, bottleneck on the Python script side\n\n## Python instrumentation example\n\nExecution of unmodified Python programs can be analyzed directly with a syntax similar to the one of `cProfile`, as a large part of the instrumentation is automated by default:\n   - Functions enter/leave\n   - Interpreter memory allocations\n   - All raised exceptions\n   - Garbage collection runs\n   - Coroutines\n\nIn some cases, a manual instrumentation which enhances or replaces the automatic one is desired. \u003cbr/\u003e\nThe example below is an equivalent of the C++ code above, but in Python:\n\n\u003cdetails\u003e\n  \u003csummary\u003e See Python manual instrumentation example code \u003c/summary\u003e\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python\n#! /usr/bin/env python3\nimport sys\nimport random\nfrom palanteer import *\n\nglobalMinValue, globalMaxValue =  0, 10\n\n# Handler (=implementation) of the example CLI, which sets the range\ndef setBoundsCliHandler(minValue, maxValue):              # 2 parameters (both integer) as declared\n    global globalMinValue, globalMaxValue\n    if minValue\u003emaxValue:                                 # Case where the CLI execution fails (non null status). The text answer contains some information about it\n        return 1, \"Minimum value (%d) shall be lower than the maximum value (%d)\" % (minValue, maxValue)\n\n    # Modify the state of the program\n    globalMinValue, globalMaxValue = minValue, maxValue\n    # CLI execution was successful (null status)\n    return 0, \"\"\n\n\ndef main(argv):\n    global globalMinValue, globalMaxValue\n\n    plInitAndStart(\"example\")                             # Start the instrumentation\n    plDeclareThread(\"Main\")                               # Declare the current thread as \"Main\", so that it can be identified more easily in the script\n    plRegisterCli(setBoundsCliHandler, \"config:setRange\", \"min=int max=int\", \"Sets the value bounds of the random generator\")  # Declare the CLI\n    plFreezePoint()                                       # Add a freeze point here to be able to configure the program at a controlled moment\n\n    plBegin(\"Generate some random values\")\n    for i in range(100000):\n        value = int(globalMinValue + random.random()*(globalMaxValue+1-globalMinValue))\n        plData(\"random data\", value)                      # Here are the \"useful\" values\n    plEnd(\"\")                                             # Shortcut for plEnd(\"Generate some random values\")\n\n    plStopAndUninit()                                     # Stop and uninitialize the instrumentation\n\n# Bootstrap\nif __name__ == \"__main__\":\n    main(sys.argv)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\u003c/details\u003e\n\n\n## Scripting example\n\nBoth examples above (C++ and Python) can be remotely controlled with a simple Python script.\n\nTypical usages are:\n  - Tests based on stimulation/configuration with CLI and events observation, as data can also be traced\n  - Evaluation of the program performance\n  - Monitoring\n  - ...\n\n\u003cdetails\u003e\n  \u003csummary\u003e See a scripting example code (Python) \u003c/summary\u003e\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python\n#! /usr/bin/env python3\nimport sys\nimport palanteer_scripting as ps\n\ndef main(argv):\n    if len(sys.argv)\u003c2:\n        print(\"Error: missing parameters (the program to launch)\")\n        sys.exit(1)\n\n    # Initialize the scripting module\n    ps.initialize_scripting()\n\n    # Enable the freeze mode so that we can safely configure the program once stopped on its freeze point\n    ps.program_set_freeze_mode(True)\n\n    # Launch the program under test\n    ps.process_launch(sys.argv[1], args=sys.argv[2:])\n    # From here, we are connected to the remote program\n\n    # Configure the selection of events to receive\n    my_selection = ps.EvtSpec(thread=\"Main\", events=[\"random data\"]) # Thread \"Main\", only the event \"random data\"\n    ps.data_configure_events(my_selection)\n\n    # Configure the program\n    status, response = ps.program_cli(\"config:setRange min=300 max=500\")\n    if status!=0:\n        print(\"Error when configuring: %s\\nKeeping original settings.\" % response)\n\n    # Disable the freeze mode so that the program resumes its execution\n    ps.program_set_freeze_mode(False)\n\n    # Collect the events as long as the program is alive or we got some events in the last round\n    qty, sum_values, min_value, max_value, has_worked = 0, 0, 1e9, 0, True\n    while ps.process_is_running() or has_worked:\n        has_worked = False\n        for e in ps.data_collect_events(timeout_sec=1.):  # Loop on received events, per batch\n            has_worked, qty, sum_values, min_value, max_value = True, qty+1, sum_values+e.value, min(min_value, e.value), max(max_value, e.value)\n\n    # Display the result of the processed collection of data\n    print(\"Quantity: %d\\nMinimum : %d\\nAverage : %d\\nMaximum : %d\" % (qty, min_value, sum_values/max(qty,1), max_value))\n\n    # Cleaning\n    ps.process_stop()            # Kills the launched process, if still running\n    ps.uninitialize_scripting()  # Uninitialize the scripting module\n\n\n# Bootstrap\nif __name__ == \"__main__\":\n    main(sys.argv)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\u003c/details\u003e\n\nThe execution of this last script, with the compile C++ as parameter, gives the following output:\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\u003e time ./remoteScript.py example\nQuantity: 100000\nMinimum : 300\nAverage : 400\nMaximum : 500\n./remoteScript.py example  0.62s user 0.02s system 24% cpu 2.587 total\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDetails can be found [here](https://dfeneyrou.github.io/palanteer/index.html#overview/commonfeatures/remotecontrol).\n\n## Logging\n\nLogs are timestamped printf-like messages that contain a severity level and a category for easier filtering.\n\nNanosecond efficiency is reached by leveraging compile-time pre-computations and deferring formatting on the viewer side. \u003cbr/\u003e\nConsole display can also be enabled dynamically, for easy local debugging.\n\nExample:\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++\nplLogDebug(\"input\", \"Key '%c' pressed\", pressedKeyChar);\n\nplLogInfo(\"computation result\", \"The resulting value of the phase %-20s is %g with the code 0x%08x\",\n          phaseStr, floatResult, errorCode);\n\nplLogWarn(\"phase\", \"End of a computation\");\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAn [internal comparison](https://dfeneyrou.github.io/palanteer/index.html#easyandefficientlogging) with the popular `spdlog` and the performant `Nanolog` (Standford) shows that`Palanteer`:\n  - is ~50x faster at runtime than `spdlog` and only twice slower than `Nanolog`\n  - is 6x faster for compiling a log call than `spdlog` and 10x faster than `Nanolog`\n  - provides more flexibility on the log selection at compile time, and the possibility to obfuscate all static strings.\n  - can provide more context around logs, like simultaneous tracing, and a powerful viewer for filtering and visualizing (all log arguments can be graphed)\n\n\n## Documentation\n\nThe complete documentation is accessible inside the repository, and online:\n  - [Introduction](https://dfeneyrou.github.io/palanteer/index.html)\n  - [Getting started](https://dfeneyrou.github.io/palanteer/getting_started.md.html)\n  - [Base concepts](https://dfeneyrou.github.io/palanteer/base_concepts.md.html)\n  - [C++ instrumentation API](https://dfeneyrou.github.io/palanteer/instrumentation_api_cpp.md.html)\n  - [C++ instrumentation configuration](https://dfeneyrou.github.io/palanteer/instrumentation_configuration_cpp.md.html)\n  - [Python instrumentation API](https://dfeneyrou.github.io/palanteer/instrumentation_api_python.md.html)\n  - [Scripting API](https://dfeneyrou.github.io/palanteer/scripting_api.md.html)\n  - [More](https://dfeneyrou.github.io/palanteer/more.md.html)\n\n## OS Support\n\nViewer and scripting library:\n  - Linux 64 bits\n  - Windows 10\n\nInstrumentation libraries:\n   - Linux 32 or 64 bits (tested on PC and armv7l)\n   - Windows 10\n   - Support for virtual threads\n     - in [C++](https://dfeneyrou.github.io/palanteer/instrumentation_api_cpp.md.html#c++instrumentationapi/virtualthreads) (userland threads, like fibers)\n     - in [Python](https://dfeneyrou.github.io/palanteer/instrumentation_api_python.md.html#virtualthreads) (asyncio / gevent)\n\n## Requirements\n\nPalanteer is lean, its full installation requires only usual components:\n  - a C++14+ compiler (gcc, clang or MSVC) in Windows 10 or Linux 64 bits for the viewer and scripting module\n  - a C++11+ compiler (tested with gcc, clang and MSVC) 32 or 64 bits for the C++ instrumentation library\n  - CPython 3.7+\n  - OpenGL 3.3+\n\nIn particular, the C++ single-header instrumentation library requires only C++11 or above.\n\nSee [here](https://dfeneyrou.github.io/palanteer/index.html#requirements) for more details on the requirements per component.\n\nOther dependencies are snapshotted inside this repository, so for information only:\n\n| Dependency name                  | License type                | URL                                            |\n|----------------------------------|-----------------------------|------------------------------------------------|\n| Khronos OpenGL API and Extension | MIT                         | https://www.khronos.org/registry/OpenGL/api/GL |\n| Dear ImGui                       | MIT                         | https://github.com/ocornut/imgui               |\n| stb                              | Public domain               | https://github.com/nothings/stb                |\n| Fonts 'Roboto-Medium.ttf'        | Apache License, Version 2.0 | https://fonts.google.com/specimen/Roboto       |\n| ZStandard                        | BSD                         | https://facebook.github.io/zstd                |\n| Markdeep                         | BSD                         | https://casual-effects.com/markdeep            |\n\n\n## License\n\nThe instrumentation libraries are under the MIT license.\n\nThe viewer and the Python scripting module are under the AGPLv3+.\n\nSee [LICENSE.md](LICENSE.md) for details.\n\n\n## Warning: Beta state\n\nEven if no major bugs are known and special care has been taken to test as many cases as possible, this project is young and in beta state.\n\nYour feedback and raised issues are warmly welcome to improve its quality, especially as it aims at improving software quality...\n\nThe state of the \"interfaces\" is:\n  - **Instrumentation API**: stable, no big changes planned\n  - **Client-server protocol**: still evolving. The induced constraint is that the servers and instrumentation libraries shall match.\n  - **Record storage**: still evolving. The impact of compatibility breaks is that older records cannot be read anymore.\n\nInterface stability and support of older versions is planned when the project is more mature. At the moment, such constraint would clamp down on its evolution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfeneyrou%2Fpalanteer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdfeneyrou%2Fpalanteer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfeneyrou%2Fpalanteer/lists"}