Coder Social home page Coder Social logo

amzn / hawktracer Goto Github PK

View Code? Open in Web Editor NEW
130.0 12.0 35.0 1.08 MB

HawkTracer is a highly portable, low-overhead, configurable profiling tool built in Amazon Video for getting performance metrics from low-end devices.

License: MIT License

CMake 7.15% C++ 50.09% C 35.04% Lua 0.03% Python 7.41% Shell 0.29%
instrumentation performance-monitoring performance hacktoberfest

hawktracer's Introduction

Build Status Gitter chat Codacy Badge codecov Build status

HawkTracer

HawkTracer is a highly portable, low-overhead, configurable profiling tool built in Amazon Video for getting performance metrics from low-end devices.

HawkTracer is available on most popular platforms: Linux, Windows, OS X. By default, the library can be used with C and C++, but there are also wrappers for Python and Rust.

The library provides many different types of events (e.g. CPU usage event, duration tracepoint), but the list can easily be extended by the user.

Features

  • Low CPU/memory overhead
  • Multi-platform
  • Highly configurable on runtime
  • Easy build integration (CMake & pkg-config files)
  • Pre-defined and user-defined events
  • Simple macros for code instrumentation
  • Streaming events to file, through TCP/IP protocol, or handling them in custom function
  • Client for receiving event stream
  • Library for parsing event stream (so you can write your own client)

License Summary

This sample code is made available under the MIT license. (See LICENSE file)

Getting Started

Hello World! tutorials

See the tutorial to quickly onboard to HawkTracer or check the examples directory. The tutorial step by step explains how to build and instrument the code like that:

static void hello_world()
{
    HT_G_TRACE_FUNCTION()

    for (int i = 0; i < 100; i++)
    {
        HT_TP_G_STRACEPOINT("iteration")
        printf("2 * %d = %d\n", i, 2*i);

        std::string txt = "Iteration (mod 10): " + std::to_string(i % 10);
        HT_TP_G_DYN_STRACEPOINT(txt.c_str());
        printf("text: %s\n", txt.c_str());
    }
}

You can also follow instructions below to get HawkTracer up and running.

Building library

$ mkdir build       # It'll be different on Windows
$ cd build
$ cmake ..
$ cmake --build .   # This instead of make, so we don't need extra instructions for Windows

Attaching HawkTracer to a project to profile

Build system integration

CMake-based projects

If you use CMake build system, you can use following code to attach HawkTracer library to your project:

project(your_project)

# optionally, you might define a path to HawkTracer's CMake module
# CMake the path below should be a path to a directory where HawkTracerConfig.cmake is located, e.g.:
# list(APPEND CMAKE_MODULE_PATH "/usr/local/lib/cmake/HawkTracer")

find_package(HawkTracer REQUIRED)

add_executable(your_project main.cc)

target_link_libraries(your_project HawkTracer::hawktracer)

pkg-config

HawkTracer library provides pkg-config file which can be used to find required libraries and include paths. You can simply integrate it e.g. with your compilation command:

$ g++ my_project.cpp $(pkg-config --cflags --libs hawktracer)

Instrumenting code

Initialize library

Before you start profiling your code, you need to initialize HawkTracer library. There are 2 functions which always have to be called in projects profiled by HawkTracer: ht_init and ht_deinit. Additionally, you need to specify an event listener. HawkTracer currently provides 2 listeners:

  • TCP listener, which streams events over the network
  • File dump listener, which saves events to a file.

Moreover, HawkTracer allows to provide user-defined listeners. Code below presents example HawkTracer (un)initialization:

int main(int argc, char** argv)
{
  ht_init(argc, argv); // initialize library
  HT_Timeline* timeline = ht_global_timeline_get(); // timeline, where all events are posted. You can define your own timeline, or use global timeline
  const size_t buffer_size = 4096; // size of internal listener's buffer
  ht_file_dump_listener_register(ht_global_timeline_get(), "hello-world-out.htdump", 2048, NULL); // create listener and attach it to timeline

  // your code goes here...

  ht_deinit(); // uninitialize library

  return 0;
}

The code registers file dump listener, which saves all the events to a file file_name.htdump. The file should be then converted to a viewer's format (see here for details).

Instrumenting the code

HawkTracer requires explicit code instrumentation. The library provides a few helper macros for reporting data to a timeline:

// Pushes any type of event to a timeline
HT_TIMELINE_PUSH_EVENT(TIMELINE, EVENT_TYPE, EVENT_PARAMETERS,...)

// Reports a duration of specific block of code (available only for C++ or C GNU compiler)
HT_TRACE(TIMELINE, LABEL)

// The same as above, but automatically sets label to current function name
HT_TRACE_FUNCTION(TIMELINE)

There are few macros which report events to a global timeline, they're prefixed with G_:

HT_G_TRACE(LABEL)
HT_G_TRACE_OPT_STATIC(LABEL)
HT_G_TRACE_OPT_DYNAMIC(LABEL)
HT_G_TRACE_FUNCTION()

For example, you can instrument following code:

void foo()
{
  HT_G_TRACE_FUNCTION() // measure duration of foo function execution

  for (int i = 0; i < 100; i++)
  {
    HT_G_TRACE_OPT_STATIC("in-loop") // measure duration of single loop iteration
    bar();
  }
}

Collect the data

For now HawkTracer provides a simple application for converting event stream to a JSON format which can be consumed by the viewing application: hawktracer-to-json. You can use it with a file or with a network stream. Assuming your events have been saved to file_name.htdump file, you can generate the JSON file running following command:

hawktracer-to-json --source file_name.htdump --output output_file.json

Analyzing the data

  • Install google-chrome or chromium browser
  • Open the browser, and open chrome://tracing/ webpage
  • Click load button and open file generated in the previous section
  • You should see a callstack with timing

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Acknowledgment

  • Hat tip to anyone who's code was used
  • Inspiration
  • etc

hawktracer's People

Contributors

alexene avatar andreasbuhr avatar brunogouveia avatar ffontaine avatar gtalis avatar justinjoy avatar loganek avatar luisbg avatar stootill avatar yak32 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hawktracer's Issues

Add Windows CI build

Currently we have a travis-ci build definition for Linux and OSX operating system. We should add Windows build as well (e.g. AppVeyor)

Python bindings not working

I like to give hawktracer a try but how do I install python bindings? cmake builds the bindings but it can't find the python interpreter. Setting PYTHONPATH fails and I get ModuleNotFoundError: No module named 'hawktracer'

ht_timeline_flush is not thread safe

I just realized that ht_timeline_flush() is not a thread safe API even if we specify true for HT_Boolean thread_safe parameter in ht_timeline_create().

If it is design or limitation, it is fine but it would be great if there is good documentation about what "thread_safe" for ht_timeline_create() covers.

As a side note, I discovered this when I tried to call ht_timeline_flush() for each timelines before I call ht_file_dump_listener_flush() so that I can make sure that all the data so far will be flushed to listener.

Thanks!

Tracing mixed Python / C++ code?

Has anyone written an integration for tracing python code? If so, do you have a reference?

Greetings from Belgium, by the way; I'm the American guy who asked you a couple questions at FOSDEM.

Cheers,
Andrew

Add unit tests to client target

Currently we don't have unit tests for the client (aka, hawktracer-to-json).

We should add unit tests, specially to avoid regression in fixes we have done already (e.g, issue #2).

Add integration tests for parser & library

We only have unit tests for both - parser and library, but we currently don't have any automation tests for checking if they both work together. Would be great to have integration tests to check if there are no issues with parsing a stream produced by the library.

Dynamic tracepoints mapping not found

Hello,

I'm trying to get dynamic tracepoints to work and it seems I can't capture the dynamic tracepoints correctly by connecting through TCP (tried with v10.0 and master branch).

I am calling in order something along the lines of:

ht_feature_cached_string_add_mapping_dynamic(ht_global_timeline_get(), name);

while(true) {
    ht_feature_callstack_start_int(ht_global_timeline_get(), custom_id);
    ht_feature_callstack_stop(ht_global_timeline_get());
}

hawktracer-converter prints: Cannot find mapping for label for all labels that are dynamic.

Extra details:

  • I am connecting hawktracer-converter after calling ht_feature_cached_string_add_mapping_dynamic. If hawktracer-converter is started first, it will miss all tracepoints and never connect to the server. Not sure if it's expected. I'm on OSX)
  • I also emit some scoped tracepoints emitted that work (by using a mapping file).

ID for Timeline

Hi,

It would be great if I can use multiple timelines from the same thread, and distinguish when the data is converted to .httrace and see it on Chrome tracing tool.

It looks that event->thread_id is used to map a timeline to a tid in httrace, but for this use case, we probably need ID for timeline itself and use it for tid.

Thanks!

Remove Features from registry

Registry doesn't have to keep track on the features, as they're only required within a timeline. I'd propose changing ht_timeline_set_feature() API to accept destroy callback, i.e.:

HT_API void ht_timeline_set_feature(HT_Timeline* timeline, size_t feature_type_id, void* feature, void(*destroy_feature)(void*));```

custom configuration for global timeline creation

Hi,

ht_global_timeline_get() makes it easy to use different timeline per thread, but we cannot use different configuration to create it. For example, we cannot pass larger(or smaller) buffer size.

Also, it makes a bit tricky to set up a same listener for all the global timelines. For example, if a threads are created in modules that doesn't have central manager that knows those threads, one way to set same listener to those timeline is to make global access to the listener and set it to each timeline. But it makes timeline setup codes here and there.

One idea to solve this is to make an API that we can pass a custom creation/setup function to hawktracer, which will be called back from ht_global_timeline_get(), if it is set.

How do you think?
Thanks!

GitHub Projects feature seems abandoned, remove?

The "Projects" feature of Github suggests that there is an ongoing project to release Hawktracer 0.6.0. As we are already on version 0.10.0, I guess the "Projects" feature is not used any more. I'd suggest to remove the "Release 0.6.0" project.

Add cpu usage monitor for Windows platform

We already have cpu_usage feature for linux-based platforms. Would be nice to implement the interface for windows as well, so the user experience is similar across all supported platforms

Strage lock corruption on macOS when used from rust and rayon

Follow up from AlexEne/rust_hawktracer#25

Reproduction steps:

git clone https://github.com/xiph/rav1e
cd rav1e
wget http://ultravideo.cs.tut.fi/video/Bosphorus_1920x1080_120fps_420_8bit_YUV_Y4M.7z
7z x Bosphorus_1920x1080_120fps_420_8bit_YUV_Y4M.7z
cargo run --release --features=tracing -- ./Bosphorus_1920x1080_120fps_420_8bit_YUV.y4m --tiles 8 -o /dev/null -l 30

It randomly crashes on close. You may want to use content with smaller resolution.

CMake-external-project integration may not work for C projects

It seems to me the cmake-external-project integration only works with C++ projects. With a C project, I get linker errors like

event_id_provider.cpp:(.text+0x1c): undefined reference to __cxa_guard_acquire'`

To reproduce, take this example project, rename the main.cpp to main.c, change CMakeLists.txt to reflect this change and build.
https://github.com/amzn/hawktracer/tree/f0c28d2f525a3674526d231e363de368f2a67b0e/examples/integrations/cmake-external-project

For an easy solution, I'd suggest to add an option to hawktracer.cmake. There is already an option to create a static build.

Or is there already a solution I have missed?

How to handle amalgamated libraries when building library statically

I have used your library in one of my projects and now I am trying to integrate it into the buildroot (https://buildroot.org) build system.
Everything works fine apart from the amalgamated libraries: they are built as shared libraries even though the main library is compiled statically.
When the project is cross-compiled using a full static toolchain with no support for shared libraries, the amalgamated libraries fail to build.
A couple of questions:

  • what is the usage of these libraries, compared to the main one? I failed to understand the purpose of having them.
  • what is the best way to handle them when trying to build the project in a full static way? Ignore them or building them as static libraries as well?

thanks for your help and this great project.

Example doesn't build

Since it includes hawktracer.h, which requires config.h, the example doesn't build as config.h is installed to the lib/include directory.

hawktracer-to-json generates timestamps in incorrect unit

Chrome tracing format expects timestamps and durations to be in microseconds, but hawktracer-to-json outputs data in nanoseconds. hawktracer-to-json should convert timestamps and durations to microseconds before saving it to json file.

Flushing API for file_dump_listener

In some situation, I would like to trigger flushing all the data so far in file_dump_listener. By looking at current implementation, listener doesn't flush until its buffer is full.

It would be great if there is an API to trigger flushing.
Thanks!

amalgamate.py fails with a encoding/decoding error

Generate source file /usr/src/hawktracer/.build/hawktracer.cpp
Traceback (most recent call last):
  File "/usr/src/hawktracer/tools/amalgamate.py", line 308, in <module>
    run_program(sys.argv[1:])
  File "/usr/src/hawktracer/tools/amalgamate.py", line 304, in run_program
    Amalgamator(args.root_dir, header_file, source_file).generate()
  File "/usr/src/hawktracer/tools/amalgamate.py", line 284, in generate
    self._generate_source_file()
  File "/usr/src/hawktracer/tools/amalgamate.py", line 276, in _generate_source_file
    source_file_dumper.dump_file(os.path.join(self._lib_dir, source_file))
  File "/usr/src/hawktracer/tools/amalgamate.py", line 216, in dump_file
    for line in f:
  File "/usr/lib64/python3.5/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3101: ordinal not in range(128)
python --version
Python 3.5.9

On bb3a3ac

How to use HawkTracer without an OS

I would like to use HawkTracer without an operating system, so without any threads. I am targeting an ARM Cortex-M7 microcontroller. At the moment, there is always some way of threading necessary. It would be great if it was possible to configure some build configuration variable like "HT_NO_THREADING" or similar to remove all threading related parts from the library.

Publish build artifacts

Currently users have to manually build all the libraries and executables. We should publish installers/rpm/deb packages so they can easily download it and install on their system.

Add support for platforms with different endianness

HawkTracer requires to run client and profiling application on platforms with the same endianness.
We should support different endiannness in the protocol. Probably we could define a SystemInfo event which contains information about endianness (and in the future, some other information as well).
I.e.

SystemEvent : Event {
  endianness: uint8_t
};

We should also have an easy way to push this event to a timeline.

Update documentation about listeners

Listeners is quite simple concept, but should be explained in the Core concepts section and we should also have a tutorial which shows step by step how to create new listener.

Windows releases improvements

There are a few things that can be improved with the windows releases:

  • Allow setting PATH variable in the installer
  • Changing the installer folder since now it is HawkTracer 0.6.0, this makes updating strange. Not needed since I added uninstall option.
  • Releasing a binaries in addition to the installer version.

Visualize benchmark results

Benchmarks generate nice JSON output; we could setup some service (e.g. elasticsearch) where we we upload the file, it's automatically processed and add records to the database, which then is queried to visualize performance results. We could use this results as a check for new pull requests as well.

Example benchmark output below:

{
  "context": {
    "date": "2018-05-09 22:47:59",
    "num_cpus": 4,
    "mhz_per_cpu": 3300,
    "cpu_scaling_enabled": true,
    "library_build_type": "debug"
  },
  "benchmarks": [
    {
      "name": "BenchmarkTimelineInitEvent",
      "iterations": 13621478,
      "real_time": 4.6952823473601420e+01,
      "cpu_time": 4.6881388495433463e+01,
      "time_unit": "ns"
    },
    {
      "name": "BenchmarkTimelinePushBaseEventNoListener/1024",
      "iterations": 38253731,
      "real_time": 1.8052485233748008e+01,
      "cpu_time": 1.8031429927710846e+01,
      "time_unit": "ns"
    }
  ]
}

Add memory usage monitor

We already have CPU usage monitor for Linux, I think it would be useful to have resident memory usage tracker as well.

Add feature for measuring duration of arbitrary code

Currently we have a scoped tracepoint, which allows us to measure an time of executing the code:

{
  ht_feature_callstack_start_string(timeline, "label");
  // some code
  ht_feature_callstack_start_string_stop(timeline);
}

Unfortunately we can't measure time of code which is overlapping; e.g. we can't measure time for code1+code2 and code2+code3 at the same time using the same timeline:

// code1
// code2
// code3

We should design and implement timeline feature, which would allow us to measure time of any code; something like:

HT_DurationId id1 = ht_feature_duration_start(timeline);
// code1
HT_DurationId id2 = ht_feature_duration_start(timeline);
// code2
HT_DurationNs duration1 = ht_feature_duration_stop(timeline, id1);
// code3
HT_DurationNs duration2 = ht_feature_duration_stop(timeline, id2);

TCP listener should use select() for waiting for a new client

Currently in TCPListener we use accept() function to accept new connections. However, this function is blocking, and can't be interrupted, therefore test ApplicationShouldNotCrashWhenCreatingListenerFails hangs on mac os. If we rewrite tcp listener so it uses multiplexers (select()) we can use pipes to unblock the thread.

Build failure with gcc 12

We have the following build failures on buildroot autobuilders with gcc 12:

/tmp/instance-8/output-1/build/hawktracer-2ec19d71923344148928ef45fce549eda67030a4/hawktracer.cpp: In function 'HT_Thread* ht_thread_create(ht_thread_callback_t, void*)':
/tmp/instance-8/output-1/build/hawktracer-2ec19d71923344148928ef45fce549eda67030a4/hawktracer.cpp:1006:28: error: no matching function for call to 'operator new(sizetype, std::thread*)'
 1006 |     new(&th->th) HT_Thread();
      |                            ^

Full build log: http://autobuild.buildroot.org/results/d18/d18a1b2ee6cdcb289567ae90b2d836844427b5f6/build-end.log

However, I don't know how to fix it properly, any advise is appreciated.

Remove HT_API macros

HT_API macros are used for MSVC build, where we either dllexport, or dllimport functions. However, if we use module-definition files (.def), those macros are not needed any more. We can also restore simultaneous static and dll build for the library.

Multithreaded tracepoints with the same name seem broken in chrome tracing

This is how the program output looks like:
parallel_trace

hawktracer_demo.zip

Sorry for it being in Rust, but this is what I happened to use when I noticed it:
The macro is basically a wrapper over:

ht_feature_callstack_start_string(ht_global_timeline_get(), name);
ht_feature_callstack_stop(ht_global_timeline_get());

I expect that the work is more evenly distributed between treads since that's what parallel iterator does, uses a thread pool to do the jobs in that lambda.
Timing wise, it takes about 8 seconds for processing it in parallel, vs the normal 30 seconds that it would take on a single thread so I assume that the jobs are more evenly distributed between threads.

I tested it with the following program:
Cargo.toml

[package]
name = "hawktracer_demo"
version = "0.1.0"
authors = ["Alexandru <[email protected]>"]

[dependencies]
rayon = "1.0"
rust_hawktracer = {git = "https://github.com/AlexEne/rust_hawktracer.git", features=["profiling_enabled"]}

main.rs:

#[macro_use]
extern crate rust_hawktracer;
extern crate rayon;
D:\__Projects__\Rust\hawktracer_demo\trace.bi
D:\__Projects__\Rust\hawktracer_demo\trace.jsonn

use rayon::prelude::*;
use rust_hawktracer::*;
use std::{thread, time};

fn main() {
    let instance = rust_hawktracer::start_hawktracer("trace.bin", 4096);
    println!("Hello, world!");
    
    let arr = vec![0; 3000];
    arr.par_iter().for_each(|_| {
        scoped_tracepoint!(_test);
        thread::sleep(time::Duration::from_millis(10));
    
        {
            for _ in 0..10 {
                scoped_tracepoint!(_second_tracepoint);
                thread::sleep(time::Duration::from_millis(10));
            }
        }
    });

    rust_hawktracer::stop_hawktracer(instance);
}

MacOS M1 installation not working

I'm following the installation steps listed in the official guideline https://hawktracer.github.io/doc/stable/build_install.html

Installation succeeds, but then I'm getting the following error while run it in MacOS M1 laptop

❯ hawktracer-converter        
dyld[94689]: Symbol not found: __ZN10HawkTracer11ClientUtils17CommandLineParser15register_optionENSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS1_10OptionInfoE
  Referenced from: <CED50F1E-85FA-317A-8C41-A2F5C3557917> /usr/local/bin/hawktracer-converter
  Expected in:     <no uuid> unknown
[1]    94689 abort      hawktracer-converter

However, when running directly given the full path in the build dir it runs fine

❯ ./client/hawktracer-converter        
Option --source must be specified
usage: ./client/hawktracer-converter [OPTION]...
  --help           Print this help
  --map <VALUE>    Comma-separated list of map files
  --source <VALUE> [MANDATORY] Data source description (either filename, or server address)
  --output <VALUE> Output file
  --format <VALUE> Output format. Supported formats: callgrind chrome-tracing 

Can you please help solving the installation issue? Thank you in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.