{"id":36495029,"url":"https://github.com/intel/gprofiler","last_synced_at":"2026-04-02T10:53:17.304Z","repository":{"id":37001391,"uuid":"342226763","full_name":"intel/gprofiler","owner":"intel","description":"gProfiler is a system-wide profiler, combining multiple sampling profilers to produce unified visualization of what your CPU is spending time on.","archived":false,"fork":false,"pushed_at":"2025-12-10T22:57:48.000Z","size":2364,"stargazers_count":797,"open_issues_count":128,"forks_count":70,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-12-11T10:39:23.236Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/intel/gprofiler","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/intel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-02-25T11:47:02.000Z","updated_at":"2025-12-06T14:46:31.000Z","dependencies_parsed_at":"2023-02-19T17:35:22.848Z","dependency_job_id":"3c2f4db0-0d90-41c1-9009-b0b435567c36","html_url":"https://github.com/intel/gprofiler","commit_stats":{"total_commits":620,"total_committers":42,"mean_commits":"14.761904761904763","dds":"0.34354838709677415","last_synced_commit":"cfd9ec10e92a915e273d11539ed2581f6ae9d5b4"},"previous_names":["intel/gprofiler","granulate/gprofiler"],"tags_count":106,"template":false,"template_full_name":null,"purl":"pkg:github/intel/gprofiler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intel%2Fgprofiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intel%2Fgprofiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intel%2Fgprofiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intel%2Fgprofiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/intel","download_url":"https://codeload.github.com/intel/gprofiler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/intel%2Fgprofiler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28331499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T00:36:25.062Z","status":"online","status_checked_at":"2026-01-12T02:00:08.677Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2026-01-12T02:00:13.333Z","updated_at":"2026-01-12T02:00:21.398Z","avatar_url":"https://github.com/intel.png","language":"Python","readme":"# gProfiler\ngProfiler combines multiple sampling profilers to produce unified visualization of\nwhat your CPU is spending time on, displaying stack traces of all processes running on your system\nacross native programs\u003csup id=\"a1\"\u003e[1](#perf-native)\u003c/sup\u003e (includes Golang), Java and Python runtimes, and kernel routines.\n\ngProfiler can upload its results to a [self hosted studio](https://localhost:4433) using [gprofiler performance studio]((https://github.com/intel/gprofiler-performance-studio), which aggregates the results from different instances over different periods of time and can give you a holistic view of what is happening on your entire cluster.\nTo upload results, you will have to register and generate a token on the website.\n\ngProfiler runs on Linux (on x86_64 and Aarch64; Aarch64 support is not complete yet and not all runtime profilers are supported, see [architecture support](#architecture-support)).\n\nFor installation methods, jump to [run as...](#run-as)\n\n![Granulate Performance Studio example view](https://user-images.githubusercontent.com/58514213/124375504-36b0b200-dcab-11eb-8d64-caf20687a29f.gif)\n\n# Configuration \u0026 parameters\n\nThis section describes the possible options to control gProfiler's behavior.\n\n## Output options\n\ngProfiler can produce output in two ways:\n\n* Create an aggregated, collapsed stack samples file (`profile_\u003ctimestamp\u003e.col`)\n  and a flamegraph file (`profile_\u003ctimestamp\u003e.html`). Two symbolic links (`last_profile.col` and `last_flamegraph.html`) always point to the last output files.\n\n  Use the `--output-dir`/`-o` option to specify the output directory.\n\n  If `--rotating-output` is given, only the last results are kept (available via `last_profle.col` and `last_flamegraph.html`). This can be used to avoid increasing gProfiler's disk usage over time. Useful in conjunction with `--upload-results` (explained ahead) - historical results are available in the Granulate Performance Studio, and the very latest results are available locally.\n\n  `--no-flamegraph` can be given to avoid generation of the `profile_\u003ctimestamp\u003e.html` file - only the collapsed stack samples file will be created.\n\n  The output is a collapsed file (`.col`) and its format is described [ahead](#data-format).\n\n* Send the results to the Granulate Performance Studio for viewing online with\n  filtering, insights, and more.\n\n  Use the `--upload-results`/`-u` flag. Pass the `--token` option to specify the token\n  provided by Granulate Performance Studio, and the `--service-name` option to specify an identifier\n  for the collected profiles, as will be viewed in a self hosted studio. *Profiles sent from numerous\n  gProfilers using the same service name will be aggregated together.*\n\nNote: both flags can be used simultaneously, in which case gProfiler will create the local files *and* upload\nthe results.\n\n### Network requirements\n\nWhen `--upload-results` is used, gProfiler will communicate with a self hosted studio. Make sure those domains are accessible for HTTPS access. Additionally, if you download gProfiler from the GitHub releases you'll need `https://github.com`, or if you use the Docker image you'll need the Docker registry accessible (`https://index.docker.io` by default).\n\nIf you [require an HTTPS proxy](#Using-HTTP-proxies), make sure the proxy has those domains whitelisted.\n\n## Profiling options\n* `--profiling-frequency`: The sampling frequency of the profiling, in *hertz*.\n* `--profiling-duration`: The duration of the each profiling session, in *seconds*.\n\nThe default profiling frequency is *11 hertz*. Using higher frequency will lead to more accurate results, but will create greater overhead on the profiled system \u0026 programs.\n\nFor each profiling session (each profiling duration), gProfiler produces outputs (writing local files and/or uploading the results to the Granulate Performance Studio).\n\n### Java profiling options\n\n* `--no-java` or `--java-mode disabled`: Disable profilers for Java.\n* `--no-java-async-profiler-buildids`: Disable embedding of buildid+offset in async-profiler native frames (used when debug symbols are unavailable).\n\n### Python profiling options\n* `--no-python`: Alias of `--python-mode disabled`.\n* `--python-mode`: Controls which profiler is used for Python.\n    * `auto` - (default) try with PyPerf (eBPF), fall back to py-spy.\n    * `pyperf` - Use PyPerf with no py-spy fallback.\n    * `pyspy`/`py-spy` - Use py-spy.\n    * `disabled` - Disable profilers for Python.\n\nProfiling using eBPF incurs lower overhead \u0026 provides kernel \u0026 native stacks.\n\n### PHP profiling options\n* `--php-mode phpspy`: Enable PHP profiling with phpspy.\n* `--no-php` or `--php-mode disabled`: Disable profilers for PHP.\n* `--php-proc-filter`: Process filter (`pgrep`) to select PHP processes for profiling (this is phpspy's `-P` option)\n\n### .NET profiling options\n* `--dotnet-mode=dotnet-trace`: Enable .NET profiling with dotnet-trace\n* `--no-dotnet` or `--dotnet-mode=disabled`: Disable profilers for .NET.\n\n### Ruby profiling options\n* `--no-ruby` or `--ruby-mode disabled`: Disable profilers for Ruby.\n\n### NodeJS profiling options\n* `--nodejs-mode`: Controls which profiler is used for NodeJS.\n     * `none` - (default) no profiler is used.\n     * `perf` - augment the system profiler (`perf`) results with jitdump files generated by NodeJS. This requires running your `node` processes with `--perf-prof` (and for Node \u003e= 10, with `--interpreted-frames-native-stack`). See this [NodeJS page](https://nodejs.org/en/docs/guides/diagnostics-flamegraph/) for more information.\n     * `attach-maps` - Generates perf map in runtime, see description ahead.\n\n## attach-maps\nIn this mode, gProfiler will automatically load a library based on [node-linux-perf module](https://github.com/mmarchini-oss/node-linux-perf) to all target NodeJS processes. This library enables `perf-pid.map` files generation in runtime, without requiring the app to be started with the `--perf-prof` flag, and from that point `perf` is able to symbolicate the compiled JavaScript functions, and we get JavaScript symbols properly.\n\ngProfiler uses the inspector protocol (documented [here](https://nodejs.org/en/docs/guides/debugging-getting-started/#enable-inspector)) to connect to target processes. gProfiler will send `SIGUSR1`, connect to the process and request to it load the library matching its NodeJS version (gProfiler comes built-in with arsenal of libraries for common NodeJS versions). After the library is loaded, gProfiler invokes the `perf-pid.map` generation. This is done to all running NodeJS processes - those running before gProfiler started, and done starting during gProfiler's run. Upon stopping, gProfiler stops the functionality, so processes no longer continue to write those file.  \nThis requires the entrypoint of application to be CommonJS script. (Doesn't work for ES modules)\n\n### Golang profiling options\n\nGolang profiling is based on `perf`, used via the system profiler (explained in [System profiling options](#System-profiling-options)).\n\nAs with all native programs, the Golang program must have symbols - not stripped - otherwise, additional debug info files must be provided. Without symbols info (specifically the `.symtab` section) `perf` is unable to symbolicate the stacktraces of the program. In that case gProfiler will not tag the stacks as Golang and you will not see any symbols.\n\nMake sure you are not passing `-s` to the `-ldflags` during your build - `-s` omits the symbols table; see more details [here](https://pkg.go.dev/cmd/link#hdr-Command_Line).\n\n### System profiling options\n\n* `--perf-mode`: Controls the global perf strategy. Must be one of the following options:\n    * `fp` - Use Frame Pointers for the call graph. *This is the default.*\n    * `dwarf` - Use DWARF for the call graph (adds the `--call-graph dwarf` argument to the `perf` command)\n    * `smart` - Run both `fp` and `dwarf`, then choose the result with the highest average of stack frames count, per process.\n    * `disabled` - Avoids running `perf` at all. See [perf-less mode](#perf-less-mode).\n\n## Rootless mode\ngProfiler can be run in rootless mode, profiling without root or sudo access with limited functionality by using the `--rootless` argument.\n\nProfiling is limited to perf (not java, python, ruby, etc.), and requires passing `--pids` with a list of processes owned by the current user.\n\nIf the default directories for the log file and pid file (e.g., `/var/log or /var/run`) are not writable by the current user, these must be explicitly directed to a writable path with `--log-file {LOG_FILE}` and `--pid-file {PID_FILE}` respectively. If gProfiler was run previously as root or with sudo, it will create the temporary directory `gprofiler_tmp` in the default location (usually `/tmp`) or wherever specified. If gProfiler is run again with `--rootless`, it will fail to run as it will be trying to write to the `gprofiler_tmp` directory which has already been created by `root` user. Delete this root owned directory or redirect to a different (user writable) directory and re-run with `--rootless`.\n\nSome additional configuration may be required to operate without root.\n\n### perf_event_paranoid\nBy default `/proc/sys/kernel/perf_event_paranoid` may be configured such that `perf` cannot operate without root. Consider setting to `-1` if `--rootless` indicates permission errors (this is the least secure mode, so refer to [perf-security documentation](https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html for security information)). It may also be necessary to set `perf_event_mlock_kb`.\n* -1: Allow use of (almost) all events by all users\nIgnore mlock limit after `perf_event_mlock_kb` without `CAP_IPC_LOCK`\n* 0: Disallow raw and ftrace function tracepoint access\n* 1: Disallow CPU event access\n* 2: Disallow kernel profiling\nTo make the adjusted `perf_event_paranoid` setting permanent, preserve it in `/etc/sysctl.conf` (e.g., `kernel.perf_event_paranoid = {SETTING}`).\n\n### perf_event_mlock_kb\nThis controls the size of per-cpu ring buffer not counted against mlock limit. The default value is 512 + 1 page. Depending on the value of `perf_event_paranoid`, it may be necessary to set `perf_event_mlock_kb`.\n\nTo make adjustment to `perf_event_mlock_kb` setting permanent preserve it in `/etc/sysctl.conf` (e.g., `kernel.perf_event_mlock_kb = {SETTING}`).\n\n### kptr_restrict\nThis toggle indicates whether restrictions are placed on exposing kernel addresses via `/proc` and other interfaces. In order to get better visibility into kernel callstacks in flamegraphs, `/proc/sys/kernel/kptr_restrict` can be set to `0`. For more information refer to [kptr-restrict docs](https://docs.kernel.org/admin-guide/sysctl/kernel.html#kptr-restrict).\n\n`echo 0 | sudo tee /proc/sys/kernel/kptr_restrict`\n\nTo make adjustment to `kptr_restrict` setting permanent preserve it in `/etc/sysctl.conf` (e.g., `kernel.kptr_restrict = {SETTING}`).\n\n## Other options\n\n### Using HTTP proxies\ngProfiler uses the Python `requests` package, which works with standard HTTP proxies environment, e.g `https_proxy` or `HTTPS_PROXY` (note - https and not http).\nIf running gProfiler as an executable and using `sudo`, make sure to run `sudo -E` if you have the environment variable defined (otherwise, `sudo` will forget it). Alternatively, you can run `sudo https_proxy=my-proxy /path/to/gprofiler ...`.\nIf running gProfiler as a Docker container, make sure to add `-e https_proxy=my-proxy` to the `docker run` command line (the spawned container does not inherit your set of environment variables, you have to pass it manually).\n\nIf you still get connection errors, make sure the proxy is indeed used by the profiler - in the `Failed to connect to server` error message you'll see the proxy used by the profiler (under `Proxy used:`).\n\n### Sending logs to server\n**By default, gProfiler sends logs to Granulate Performance Studio** (when using `--upload-results`/`-u` flag)\nThis behavior can be disabled by passing `--dont-send-logs` or the setting environment variable `GPROFILER_DONT_SEND_LOGS=1`.\n\n### Metrics and metadata collection\nBy default, gProfiler agent sends system metrics (CPU and RAM usage) and metadata to the Performance Studio.\nThe metadata includes system metadata like the kernel version and CPU count, and cloud metadata like the type of the instance you are running on.\nThe metrics collection will not be enabled if the `--upload-results`/`-u` flag is not set.\nOtherwise, you can disable metrics and metadata by using the following parameters:\n* Use `--disable-metrics-collection` to disable metrics collection\n* Use `--disable-metadata-collection` to disable metadata collection\n\n### Continuous mode\ngProfiler can be run in a continuous mode, profiling periodically, using the `--continuous`/`-c` flag.\nNote that when using `--continuous` with `--output-dir`, a new file will be created during *each* sampling interval.\nAggregations are only available when uploading to the Granulate Performance Studio.\n\n### Uploading profiling data from another source\ngProfiler can be used to upload external .col file to Granulate Performance Studio by using `upload-file` subcommand.\nIn case of gProfiler run volume mapping flag must be added. Example for docker usage: `docker run --name granulate-gprofiler -v \u003cpath-to-.col\u003e:\u003cpath-to-.col\u003e --pid=host --userns=host --privileged  gprofiler:latest upload-file  --token=\u003ctoken\u003e --service-name=\"\u003cservice\u003e\" --file-path \u003cpath-to-.col\u003e`\nIt is also possible to add custom start and end time (in the form of UTC ISO 8601 format time in Python timestamps) to the metadata, so that it will be properly categorized in the Granulate Performance Studio (i.e. `# {\"start_time\": \"2022-10-21T13:51:29.640637\",\"end_time\": \"2022-10-21T13:54:29.640637\", ...`)\n\n# Run as...\n\nThis section lists the various execution modes for gProfiler (as a container, as an executable, etc...).\n\n## Running as a Docker container\nRun the following to have gProfiler running continuously, uploading to Granulate Performance Studio:\n```bash\ndocker pull intel/gprofiler:latest\ndocker run --name granulate-gprofiler -d --restart=on-failure:10 \\\n    --pid=host --userns=host --privileged \\\n\tintel/gprofiler:latest -cu --token=\"\u003cTOKEN\u003e\" --service-name=\"\u003cSERVICE NAME\u003e\" [options]\n```\n\n## Running as an executable\nFirst, check if gProfiler is already running - run `pgrep gprofiler`. You should not see any output, if you do see any PIDs it means that gProfiler is running and it must be stopped before starting it again (you can stop it with `sudo pkill -TERM gprofiler`).\n\nRun the following to have gprofiler running continuously, in the background, uploading to Granulate Performance Studio:\n```bash\nwget https://github.com/intel/gprofiler/releases/latest/download/gprofiler_$(uname -m) -O gprofiler\nsudo chmod +x gprofiler\nsudo TMPDIR=/proc/self/cwd sh -c \"setsid ./gprofiler -cu --token=\\\"\u003cTOKEN\u003e\\\" --service-name=\\\"\u003cSERVICE NAME\u003e\\\" [options] \u003e /dev/null 2\u003e\u00261 \u0026\"\nsleep 1\npgrep gprofiler # make sure gprofiler has started\n```\n\nIf the `pgrep` doesn't find any process, try running without `\u003e /dev/null 2\u003e\u00261 \u0026` so you can inspect the output, and look for errors.\n\nFor non-daemon mode runes, you can remove the `setsid` and `\u003e /dev/null 2\u003e\u00261 \u0026` parts.\n\nThe logs can then be viewed in their default location (`/var/log/gprofiler`).\n\n`TMPDIR` is added because gProfiler unpacks executables to `/tmp` by default; this is done by `staticx`. For cases where `/tmp` is marked with `noexec`, we add `TMPDIR=/proc/self/cwd` to have everything unpacked in your current working directory, which is surely executable before gProfiler was started in it.\n\n## Running as systemd service\n\nYou can generate a systemd service configuration that [runs gProfiler as an executable](#running-as-an-executable) by running:\n\n``` bash\ncurl -s https://raw.githubusercontent.com/intel/gprofiler/master/deploy/systemd/create_systemd_service.sh | GPROFILER_TOKEN=\u003cTOKEN\u003e GPROFILER_SERVICE=\u003cSERVICE_NAME\u003e bash\n```\n\nThis script generates `granulate-gprofiler.service` in your working directory, and you can go ahead and install it by:\n```\nsystemctl enable $(pwd)/granulate-gprofiler.service\nsystemctl start granulate-gprofiler.service\n```\n\n## Running on Databricks\nFor Databricks, the same installation instructions as specified in the [running as an executable](#running-as-an-executable) section can be used (make sure to run them in the initialization script of your node).\n\nAdditionally, 2 more flags need to be added to gProfiler's commandline: `--disable-pidns-check --perf-mode=none`. You can add them right after the `--service-name` argument.\n\n* `--disable-pidns-check` is required because gProfiler won't run in the init PID NS.\n* `--perf-mode=none` is required because gProfiler will not have permissions to run system-wide `perf`, so we will profile only runtime processes, such as Java. See [perf-less mode](#perf-less-mode) for more information.\n\n\nIn case gProfiler spots this property is redacted, gProfiler will use the\n`spark.databricks.clusterUsageTags.clusterName` property as service name.\n\n\n## Running as a Kubernetes DaemonSet\nSee [gprofiler.yaml](deploy/k8s/gprofiler.yaml) for a basic template of a DaemonSet running gProfiler.\nMake sure to insert the `GPROFILER_TOKEN` and `GPROFILER_SERVICE` variables in the appropriate location!\n\n### Installing with Helm Chart\nLike with the DaemonSet, make sure to insert the `GPROFILER_TOKEN` and `GPROFILER_SERVICE` variables in the appropriate location.\n```\ncd deploy/k8s/helm-charts\nhelm install --set gprofiler.token=\"GPROFILER_TOKEN\" --set gprofiler.serviceName=\"GPROFILER_SERVICE\" gprofiler .\n\n# To view additional configuration options you can run:\nhelm show values .\n```\n\n### OpenShift SCCs\n\nIf your OpenShift cluster uses [SCCs](https://docs.openshift.com/container-platform/4.12/authentication/managing-security-context-constraints.html), the gProfiler Pods might get an error `FailedCreate` with the reason `unable to validate against any security context constraint`.\n\nIf this happens, we must grant the `privileged` SCC to the gProfiler DaemonSet to have the Pods scheduled.\n\nThis is done by creating a `Role` that's allowed to use the `privileged` SCC, then granting that `Role` via a `RoleBinding` to a `ServiceAccount` that is used in gProfiler's `DaemonSet`. The 3 objects (`ServiceAccount`, `Role`, `RoleBinding`) can be found in [scc.yaml](deploy/k8s/openshift/scc.yaml). After applying that file, all you need to do is add `serviceAccountName: granulate-service-account` to the gProfiler Pod spec, re-apply the `DaemonSet` and verify that created Pods have the `openshift.io/scc: privileged` annotation, which means they have successfully used the SCC.\n\n## Running as an ECS (Elastic Container Service) Daemon service\n\n### Creating the ECS Task Definition\n- Go to ECS, and [create a new task definition](https://console.aws.amazon.com/ecs/home?region=us-east-1#/taskDefinitions/create)\n- Choose EC2, and click `Next Step`\n- Scroll to the bottom of the page, and click `Configure via JSON` \\\n![Configure via JSON button](https://user-images.githubusercontent.com/74833655/132983629-163fdb87-ec9a-4201-b557-e0ae441e2595.png)\n- Replace the JSON contents with the contents of the [gprofiler_task_definition.json](deploy/ecs/gprofiler_task_definition.json) file and **Make sure you change the following values**:\n  - Replace `\u003cTOKEN\u003e` in the command line with your token you got from a self hosted studio site.\n  - Replace `\u003cSERVICE NAME\u003e` in the command line with the service name you wish to use.\n- **Note** - if you wish to see the logs from the gProfiler service, be sure to follow [AWS's guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_awslogs.html#create_awslogs_loggroups)\n  on how to auto-configure logging, or to set it up manually yourself.\n- Click `Save`\n- Click `Create`\n\n### Deploying the gProfiler service\n\n* Go to your [ECS Clusters](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters) and enter the relevant cluster\n* Click on `Services`, and choose `Create`\n* Choose the `EC2` launch type and the `granulate-gprofiler` task definition with the latest revision\n* Enter a service name\n* Choose the `DAEMON` service type\n* Click `Next step` until you reach the `Review` page, and then click `Create Service`\n\n## Running on an AWS Fargate service\n\nAt the time of this writing, Fargate does not support `DAEMON` tasks (see [this](https://github.com/aws/containers-roadmap/issues/971) tracking issue).\n\nSince Fargate containers don't run with the full set of Linux capabilities, some of the profilers are not supported at all, and others require modifying the Fargate container definition to add the `SYS_PTRACE` capability, which is not included by default.\n\n| Runtime                    | Supported               |\n|----------------------------|-------------------------|\n| perf (native, Golang, ...) | No                      |\n| Java (async-profiler)      | Yes                     |\n| Python (py-spy)            | Yes (with `SYS_PTRACE`) |\n| Python (PyPerf eBPF)       | No                      |\n| Ruby (rbspy)               | Yes (with `SYS_PTRACE`) |\n| PHP (phpspy)               | Yes (with `SYS_PTRACE`) |\n| NodeJS (perf)              | No                      |\n| .NET (dotnet-trace)        | Yes                     |\n\nFurthermore, Fargate does not allow using `\"pidMode\": \"host\"` in the task definition (see documentation of `pidMode` [here](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskDefinition.html)). Host PID is required for gProfiler to be able to profile processes running in other containers (in case of Fargate, other containers under the same `containerDefinition`).\n\nSo in order to deploy gProfiler, we need to modify a container definition to include running gProfiler alongside the actual application. This can be done with the following steps:\n1. Modify the `command` \u0026 `entryPoint` parameters of your entry in the `containerDefinitions` array. The new command should include downloading of gProfiler \u0026 executing it in the background, and `entryPoint` will be `[\"/bin/bash\"]`.\n\n    For example, if your default `command` is `[\"python\", \"/path/to/my/app.py\"]`, we will now change it to: `[\"-c\", \"(wget https://github.com/intel/gprofiler/releases/latest/download/gprofiler -O /tmp/gprofiler; chmod +x /tmp/gprofiler; /tmp/gprofiler -cu --token=\u003cTOKEN\u003e --service-name=\u003cSERVICE NAME\u003e) \u0026 python /path/to/my/app.py\"]`.\n\n    Make sure to:\n    - Replace `\u003cTOKEN\u003e` in the command line with your token you got from a self hosted studio site.\n    - Replace `\u003cSERVICE NAME\u003e` in the command line with the service name you wish to use.\n\n    This new command will start the downloading of gProfiler in the background, then run your application. Make sure to JSON-escape any characters in your command line! For example, `\"` are replaced with `\\\"`.\n\n    Additionally, we will set `entryPoint` to `[\"/bin/bash\"]`. If you had used `entryPoint` prior to incorporating gProfiler, make sure to use it in the new `command`.\n\n    gProfiler will assume `--disable-pidns-check` and `--perf-mode none` were given. These flags are explained in [running-on-databricks](#running-on-databricks).\n\n    gProfiler and its installation process will send the outputs to your container's stdout \u0026 stderr. After verifying that everything works, you can append `\u003e /dev/null 2\u003e\u00261` to the gProfiler command parenthesis (in this example, before the `\u0026 python ...`) to prevent it from spamming your container logs.\n\n    This requires your image to have `wget` installed - you can make sure `wget` is installed, or substitute the `wget` command with `curl -SL https://github.com/intel/gprofiler/releases/latest/download/gprofiler --output /tmp/gprofiler`, or any other HTTP-downloader you wish.\n2. This step is **required** if you wish to profile a runtime environment that requires `SYS_PTRACE` per the table mentioned above, in the beginning of the Fargate section. If you need to add `SYS_PTRACE` for your runtime environment - currently that's for Python, Ruby and PHP - add `linuxParameters` to the container definition (this goes directly in your entry in `containerDefinitinos`):\n   ```\n   \"linuxParameters\": {\n     \"capabilities\": {\n       \"add\": [\n         \"SYS_PTRACE\"\n       ],\n     },\n   },\n   ```\n\nAlternatively, you can download gProfiler in your `Dockerfile` to avoid having to download it every time in run-time. Then you just need to invoke it upon container start-up.\n\n## Running as a docker-compose service\nYou can run a gProfiler container with `docker-compose` by using the template file in [docker-compose.yml](deploy/docker-compose/docker-compose.yml).\nStart by replacing the `\u003cTOKEN\u003e` and `\u003cSERVICE NAME\u003e` with values in the `command` section -\n* `\u003cTOKEN\u003e` should be replaced with your personal token from a self hosted studio site (in the [Install Service](https://localhost:4433/installation) section)\n* The `\u003cSERVICE NAME\u003e` should be replaced with whatever service name you wish to use\n\nOptionally, you can add more command line arguments to the `command` section. For example, if you wish to use the `py-spy` profiler, you can add `--python-mode pyspy` to the commandline.\n\n**To run it, run the following command:**\n  ```bash\n  docker-compose -f /path/to/docker-compose.yml up -d\n  ```\n\n## Running on Google Dataproc\nTo run gProfiler on your cluster, you will need to add an [initialization action](https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/init-actions)\nthat will install the agent on all of your workers when the cluster is created.\n\nFirst, upload the gProfiler [initialization action script](./deploy/dataproc/gprofiler_initialization_action.sh) file to your Google Cloud Storage bucket -\n```shell\ngsutil cp gprofiler_initialization_action.sh gs://\u003cYOUR BUCKET\u003e\n```\nIf you don't have a Google Storage bucket, make sure you create one ([documentation](https://cloud.google.com/storage/docs/creating-buckets)).\nThen, create your Dataproc cluster with the `--initialization-actions` flag -\n```shell\nexport TOKEN='\u003cTOKEN\u003e' \u0026\u0026 \\\nexport SERVICE='\u003cSERVICE NAME\u003e' \u0026\u0026 \\\ngcloud dataproc clusters create \u003cCLUSTER NAME\u003e \\\n--initialization-actions gs://\u003cYOUR BUCKET\u003e/gprofiler_initialization_action.sh \\\n--metadata gprofiler-token=\"$TOKEN\",gprofiler-service=\"$SERVICE\",enable-stdout=\"1\" --region \u003cREGION\u003e\n```\n**Note** - make sure to replace the placeholders with the appropriate values -\n  - Replace `\u003cTOKEN\u003e` in the command line with your token you got from a [self hosted studio](https://localhost:4433/installation) site.\n  - Replace `\u003cSERVICE NAME\u003e` in the command line with the service name you wish to use.\n  - Replace `\u003cYOUR BUCKET\u003e` with the bucket name you have uploaded the gProfiler initialization action script to.\n  - Replace `\u003cCLUSTER NAME\u003e` with the cluster name you wish to use\n  - Replace `\u003cREGION\u003e` with the region you wish to use\n\n### Debugging problems\nIf you are experiencing issues with your gProfiler installation (such as no flamegraphs available in a self hosted studio)\nafter waiting for more than 1 hour) you can look at gProfiler's logs and see if there are any errors. \\\nTo see gProfiler's logs, you must enable its output by providing `enable-stdout=\"1\"` in the cluster metadata when creating the Dataproc cluster. You can use the example above.\nWait at least 10 minutes after creating your cluster, and then you can SSH into one of your cluster instances via either Dataproc's web interface or the command line.\nAfter connecting to your instance, run the following command:\n```shell\ntail -f /var/log/dataproc-initialization-script-0.log\n```\nIf you have more than one initialization script, try running the command with an increasing number instead of `0` in the command find the appropriate gProfiler log file.\n\n### Disabling gProfiler stdout output\nBy default, gProfiler's output is written to the Dataproc initialization script output file (`/var/log/dataproc-initialization-script-{Incrementing number}.log`).\nIf you wish to disable this behaviour, change the `enable-stdout` metadata variable value to \"0\" (the default is \"1\").\n\n## Running on AWS EMR\nTo run gProfiler on your AWS EMR cluster, add a bootstrap action that will launch gProfiler on each\nnode when the cluster is provisioned. You will need to provide the token and service name as described below.\n\n1. Upload the [gProfiler bootstrap action file](./deploy/emr/gprofiler_action.sh) to an S3 bucket:\n\n   ```sh\n   aws s3 cp gprofiler_action.sh s3://\u003cBUCKET\u003e/gprofiler_action.sh\n   ```\n\n2. Add the bootstrap action when creating the cluster. You can do this with [the AWS Console or with the AWS CLI](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-bootstrap.html?icmpid=docs_emr_help_panel_cluster-bootstrap#custom-bootstrap):\n\n   In the steps below, make sure to:\n     - Replace `\u003cBUCKET\u003e` with the bucket where `gprofiler_action.sh` was uploaded.\n     - Replace `\u003cTOKEN\u003e` with the token you got from a [self hosted studio](https://localhost:4433/installation) site.\n     - Replace `\u003cSERVICE\u003e` with the service name you wish to use.\n\n   With AWS CLI:\n     ```sh\n     aws emr create-cluster --name \"My cluster\" ... --bootstrap-actions Path=\"s3://\u003cBUCKET\u003e/gprofiler_action.sh\",Args=\"[--token=\u003cTOKEN\u003e,--service-name=\u003cSERVICE\u003e]\"\n     ```\n\n   With new AWS Console:\n     - Create a new cluster.\n     - Under **Bootstrap actions**, choose **Add**, and fill in the fields:\n       - **Name**: gProfiler\n       - **Script location**: `s3://\u003cBUCKET\u003e/gprofiler_action.sh`\n       - **Arguments**: `--token=\u003cTOKEN\u003e --service-name=\u003cSERVICE\u003e`\n       - Example: ![Add bootstrap action](./deploy/emr/add_bootstrap_action.png)\n     - Final result should look similar to this: ![Bootstrap actions](./deploy/emr/bootstrap_actions.png)\n\n## Running via an Ansible playbook\nDownload the [playbook](./deploy/ansible/gprofiler_playbook.yml) and run it this way:\n```\nansible-playbook -i ... gprofiler_playbook.yml --extra-vars \"gprofiler_token='\u003cTOKEN\u003e'\" --extra-vars \"gprofiler_service='\u003cSERVICE NAME\u003e'\"\n```\n\n**Note** - the playbook defaults to `hosts: all`, make sure to modify the pattern to your liking before running.\n\nThe playbook defines 2 more variables:\n* `gprofiler_path` - path to download gProfiler to, `/tmp/gprofiler` by default.\n* `gprofiler_args` - additional arguments to pass to gProfiler, empty by default. You can use it to pass, for example, `'--profiling-frequency 15'` to change the frequency.\n\n## Running from source\ngProfiler requires Python 3.10+ to run.\n\n```bash\npip3 install -r requirements.txt\n./scripts/copy_resources_from_image.sh\n```\n\nThen, run the following **as root**:\n```bash\npython3 -m gprofiler [options]\n```\n\n# Theory of operation\ngProfiler invokes `perf` in system wide mode, collecting profiling data for all running processes.\nAlongside `perf`, gProfiler invokes runtime-specific profilers for processes based on these environments:\n* Java runtimes (version 7+) based on the HotSpot JVM, including the Oracle JDK and other builds of OpenJDK like AdoptOpenJDK and Azul Zulu.\n  * Uses async-profiler.\n* The CPython interpreter, versions 2.7 and 3.5-3.10.\n  * eBPF profiling (based on PyPerf) requires Linux 4.14 or higher; see [Python profiling options](#python-profiling-options) for more info.\n  * If eBPF is not available for whatever reason, py-spy is used.\n* PHP (Zend Engine), versions 7.0-8.0.\n  * Uses [Granulate's fork](https://github.com/Granulate/phpspy/) of the phpspy project.\n* Ruby versions (versions 1.9.1 to 3.0.1)\n  * Uses [Granulate's fork](https://github.com/Granulate/rbspy) of the [rbspy](https://github.com/rbspy/rbspy) profiler.\n* NodeJS (version \u003e= 10 for functioning `--perf-prof`):\n  * Uses `perf inject --jit` and NodeJS's ability to generate jitdump files. See [NodeJS profiling options](#nodejs-profiling-options).\n  * Can also generate perf maps at runtime - see [attach-maps](#attach-maps) option.\n* .NET runtime\n  * Uses dotnet-trace.\n\nThe runtime-specific profilers produce stack traces that include runtime information (i.e, stacks of Java/Python functions), unlike `perf` which produces native stacks of the JVM / CPython interpreter.\nThe runtime stacks are then merged into the data collected by `perf`, substituting the *native* stacks `perf` has collected for those processes.\n\n## Architecture support\n\n| Runtime                    | x86_64                            | Aarch64                           |\n|----------------------------|-----------------------------------|-----------------------------------|\n| perf (native, Golang, ...) | :heavy_check_mark:                | :heavy_check_mark:                |\n| Java (async-profiler)      | :heavy_check_mark:                | :heavy_check_mark:                |\n| Python (py-spy)            | :heavy_check_mark:                | :heavy_check_mark:                |\n| Python (PyPerf eBPF)       | :heavy_check_mark:                | :x:                               |\n| Ruby (rbspy)               | :heavy_check_mark:                | :heavy_check_mark:                |\n| PHP (phpspy)               | :heavy_check_mark:                | :heavy_check_mark: (experimental) |\n| NodeJS (perf)              | :heavy_check_mark:                | :heavy_check_mark:                |\n| .NET (dotnet-trace)        | :heavy_check_mark: (experimental) | :heavy_check_mark: (experimental) |\n\n## perf-less mode\n\nIt is possible to run gProfiler without using `perf` - this is useful where `perf` can't be used, for whatever reason (e.g permissions). This mode is enabled by `--perf-mode disabled`.\n\nIn this mode, gProfiler uses runtime-specific profilers only, and their results are concatenated (instead of scaled into the results collected by `perf`). This means that, although the results from different profilers are viewed on the same graph, they are not necessarily of the same scale: so you can compare the samples count of Java to Java, but not Java to Python.\n\n## Data format\n\nThis section describes the data format output by the profiler. Some of it is relevant to the local output files (`.col`) files and some of it is relevant both for the local output files and for the data as viewable in the Performance Studio.\n\n### Collapsed files\n\nThe collapsed file (`.col`) is a [collapsed/folded stacks file](https://github.com/brendangregg/FlameGraph#2-fold-stacks) that'll be written locally per profiling session if gProfiler was invoked with the `-o` switch.  \nThe file begins with a \"comment line\", starting with `#`, which contains a JSON of metadata about the profile. Following lines are *stacks* - they consist of *frames* separated by `;`, with the ending of each line being a space followed by a number - how many *samples* were collected with this stack.  \nThe first frame of each stack is an index in the application metadata array (which is part of the aforementioned JSON), for the process recorded in this sample.  \nThe second frame is the container name that the process recorded in this sample runs in; if the process is not running in a container, this frame will be empty.  \nThe third frame is the process name - essentially the process `comm` in Linux.  \nAll following frames are the output of the profiler which emitted the sample (usually - function names). Frames are described in [frame format](#frame-format).\n\n### Application identifiers\n\nAn application identifier (\"appid\" for short) is an optional frame that follows the process name frame. This frame has the format `appid: ...`. Per profiled process, gProfiler attempts to extract its appid, and \"inject\" it into the profile collected for that process - the purpose is to give the user more context about the source application of the proceeding frames.  \nFor example, a Python application invoked as `cd /path/to/my/app \u0026\u0026 python myscript.py` will have the following appid: `appid: python: myscript.py (/path/to/my/app/myscript.py)` - this appid tells us it's a Python application running `myscript.py` and gives in parenthesis the absolute path of the executed script.\n\ngProfiler currently supports appids for Java, Python, NodeJS \u0026 Ruby, with each runtime having possibly more than one implementation (e.g in Python, the appid of a Gunicorn-based application is decided differently, because the app doesn't specify a \"Python script\" to invoke, but instead specifies a WSGI application spec). You can see the various implementations in [application_identifiers.py](./gprofiler/metadata/application_identifiers.py)\n\nCollection of appids is enabled by default and can be disabled with the `--disable-application-identifiers` switch.\n\n### Frame format\n\nEach frame represents a function as identified by gProfiler. Since gProfiler aggregated frames collected by different profilers, the frame format differs depending on which profiler collected it, and from which runtime it originates (e.g Python vs Java).\nAdditionally, each frame has a suffix which designates the profiler it originated from and the logical \"source\" for the frame - is it Java code? Kernel code? Native library code?\n\n| Runtime                               | Frame Format                                                                                                                                                                            | Suffix                                                                                                   |\n|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|\n| Native - C, C++, Rust (perf)          | Symbol name                                                                                                                                                                             | None                                                                                                     |\n| Golang (perf)                         | Symbol name                                                                                                                                                                             | None                                                                                                     |\n| Java (async-profiler)                 | Method FQN + signature, per [async-profiler's `-g` switch](https://github.com/jvm-profiling-tools/async-profiler#profiler-options). `;`s in the method signature are replaced with `\\|` | [Per asnyc-profiler `-a` switch](https://github.com/jvm-profiling-tools/async-profiler#profiler-options) |\n| Native (async-profiler)               | Symbol name                                                                                                                                                                             | None                                                                                                     |\n| Python (PyPerf)                       | `package.(instance class if it's a method/classmethod).function_name (filename.py:line_number)`                                                                                         | `_[p]`                                                                                                   |\n| Native (PyPerf)                       | Symbol name                                                                                                                                                                             | `_[pn]`                                                                                                  |\n| Python (py-spy)                       | `package.function_name (filename.py:line_number)`                                                                                                                                       | `_[p]`                                                                                                   |\n| NodeJS (perf)                         | Per NodeJS                                                                                                                                                                              | None                                                                                                     |\n| Ruby (rbspy)                          | Per rbspy                                                                                                                                                                               | `_[rb]`                                                                                                  |\n| PHP (phpspy)                          | Per phpspy                                                                                                                                                                              | `_[php]`                                                                                                 |\n| .NET (dotnet-trace)                   | Per dotnet-trace                                                                                                                                                                        | `_[net]`                                                                                                 |\n| Kernel (perf, async-profiler, PyPerf) | Function name                                                                                                                                                                           | `_[k]`                                                                                                   |\n\n# Security Concerns\n\nConsider reviewing Docker security docs described in https://docs.docker.com/engine/security/\nIf you're using Docker, it's recommended to enable the following security settings if required by your organization and applicable:\n* Enable AppArmor Profile (https://docs.docker.com/engine/security/apparmor/)\n* Enable SELinux \n* Update the IP address bindings in the docker-compose file (they default to 0.0.0.0 on all interfaces) to your specific hosts.  \n  * Default port settings in docker-compose are: \"8080:80\" and \"4433:443\"\n  * You can bind them to your desired ip by setting them to: \"{my_ip}:8080:80\" and \"{my_ip}:4433:443\"\n* Mount the container's root file system as read only\n* Restrict the container from acquiring additional privileges using --no-new-privilege\n* Make sure the Docker commands always make use of the latest version of their images\n\nBe aware that when deployed as a container...\n\n* gProfiler may require privileged mode to operate.  Make sure you understand the security implications by reviewing the [Docker security docs](https://docs.docker.com/engine/security/) \n* The host PID and user namespace will be shared with gProfiler to allow it to run as root outside the container.  Consider using [rootless mode](#rootless-mode)\n\n\n# Building\n\nPlease refer to the [building](./CONTRIBUTING.md#building) section.\n\n# Contribute\nWe welcome all feedback and suggestion through Github Issues:\n* [Submit bugs and feature requests](https://github.com/intel/gprofiler/issues)\n* Upvote [popular feature requests](https://github.com/intel/gprofiler/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement+sort%3Areactions-%2B1-desc+)\n\n## Releasing a new version\n1. Update `__version__` in `__init__.py`.\n2. Create a tag with the same version (after merging the `__version__` update) and push it.\n\nWe recommend going through our [contribution guide](./CONTRIBUTING.md) for more details.\n\n# Credits\n* [async-profiler](https://github.com/jvm-profiling-tools/async-profiler) by [Andrei Pangin](https://github.com/apangin). See [our fork](https://github.com/Granulate/async-profiler).\n* [py-spy](https://github.com/benfred/py-spy) by [Ben Frederickson](https://github.com/benfred). See [our fork](https://github.com/Granulate/py-spy).\n* [bcc](https://github.com/iovisor/bcc) (for PyPerf) by the IO Visor project. See [our fork](https://github.com/Granulate/bcc).\n* [phpspy](https://github.com/adsr/phpspy) by [Adam Saponara](https://github.com/adsr). See [our fork](https://github.com/Granulate/phpspy).\n* [rbspy](https://github.com/rbspy/rbspy) by the rbspy project. See [our fork](https://github.com/Granulate/rbspy).\n* [dotnet-trace](https://github.com/dotnet/diagnostics/tree/main/src/Tools/dotnet-trace)\n* [Datadog Agent Integrations](https://github.com/DataDog/integrations-core) for the Spark, YARN metrics\n\n# Footnotes\n\n\u003ca name=\"perf-native\"\u003e1\u003c/a\u003e: To profile native programs that were compiled without frame pointers, make sure you use the `--perf-mode smart` (which is the default). Read more about it in the [Profiling options](#profiling-options) section[↩](#a1)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintel%2Fgprofiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fintel%2Fgprofiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintel%2Fgprofiler/lists"}