|
| 1 | +# DTrace in PonyC |
| 2 | + |
| 3 | +[DTrace](http://dtrace.org/guide/preface.html) provides a library for dynamic |
| 4 | +tracing of events. This document describes the implementation of DTrace within |
| 5 | +the Pony compiler. In particular, it focuses on how to use and extend the DTrace |
| 6 | +implementation within Pony. |
| 7 | + |
| 8 | +DTrace is only available for MacOS and BSD. For Linux there is an alternative |
| 9 | +called [SystemTap](https://sourceware.org/systemtap/). SystemTap uses the same |
| 10 | +resources as DTrace, but uses different scripts. You will find more information |
| 11 | +on using SystemTap within the Pony compiler [here](../systemtap/README.md). |
| 12 | + |
| 13 | +## Using DTrace scripts for Pony |
| 14 | + |
| 15 | +You can find various example DTrace scripts in `example/dtrace/`. To run these |
| 16 | +scripts, you can use a command in the form of `[script] -c [binary]`. You need |
| 17 | +to use a PonyC compiler compiled with the DTrace flag to use DTrace. To compile |
| 18 | +a DTrace enabled compiler, you can use the following command: `make |
| 19 | +config=release use=dtrace`. |
| 20 | + |
| 21 | +We can also execute a script using the dtrace command. This is necessary if the |
| 22 | +script does not contain a "Shebang". We can do it using the following command: |
| 23 | +`dtrace -s [script] -c [binary]`. |
| 24 | + |
| 25 | +### MacOS 10.11+ |
| 26 | + |
| 27 | +MacOS El Capitan for the first time included "System Integrity Protection". This |
| 28 | +feature does not allow for all DTrace features to be used. This includes custom |
| 29 | +DTrace providers. To get around this problem, the following steps can be |
| 30 | +followed: |
| 31 | + |
| 32 | +1. Boot your Mac into Recovery Mode. |
| 33 | +2. Open the Terminal from the Utilities menu. |
| 34 | +3. Then use the following commands: |
| 35 | + |
| 36 | +```bash |
| 37 | + |
| 38 | +csrutil clear # restore the default configuration first |
| 39 | + |
| 40 | +csrutil enable --without dtrace # disable dtrace restrictions *only* |
| 41 | + |
| 42 | +``` |
| 43 | + |
| 44 | +After completing these steps your Mac should be able to use DTrace after a |
| 45 | +restart. For more information visit the following article: |
| 46 | +[link](http://internals.exposed/blog/dtrace-vs-sip.html). |
| 47 | + |
| 48 | +## Writing scripts for DTrace in Pony |
| 49 | + |
| 50 | +The following paragraph will inform you on the Pony provider and its probes for |
| 51 | +DTrace. We refer to the [DTrace |
| 52 | +documentation](http://dtrace.org/guide/preface.html) for more information on the |
| 53 | +syntax and possibilities. |
| 54 | + |
| 55 | +The Pony provider for DTrace consists of DTrace probes implemented in the |
| 56 | +Runtime. A binary compiled with DTrace enabled will allow the user access to the |
| 57 | +information of the probes. You can find a list of all probes and their arguments |
| 58 | +in [`src/common/dtrace_probes.d`](../../src/common/dtrace_probes.d). The |
| 59 | +following is a toy example DTrace script: |
| 60 | + |
| 61 | +``` |
| 62 | +
|
| 63 | +pony$target:::gc-start |
| 64 | +{ |
| 65 | + @ = count(); |
| 66 | +} |
| 67 | +
|
| 68 | +END |
| 69 | +{ |
| 70 | + printa(@); |
| 71 | +} |
| 72 | +
|
| 73 | +``` |
| 74 | + |
| 75 | +This script increases a counter every time the "GC Start" probe is *fired* and |
| 76 | +prints it result at the end. Note the way in which we access the probe. It |
| 77 | +consists of two parts: the first part is the provider and the second part, after `:::` |
| 78 | +is the name of the probe. The provider is during runtime appended by the process |
| 79 | +ID. In this example we use the `$target` variable to find the process ID. |
| 80 | +Another option is to use `pony*`, but note that this could match many processes. |
| 81 | +The name of the probe are also different from the names in |
| 82 | +[`src/common/dtrace_probes.d`](../../src/common/dtrace_probes.d). In Dtrace |
| 83 | +scripts you have to replace the `__` in the names by `-`. |
| 84 | + |
| 85 | +To make these scripts executable, like the ones in the examples, we use the |
| 86 | +following "Shebang": `#!/usr/bin/env dtrace -s`. Extra options can be added to |
| 87 | +improve its functionality. |
| 88 | + |
| 89 | +## Extending the DTrace implementation in Pony |
| 90 | + |
| 91 | +You can extend the DTrace implementation by adding more probes or extra |
| 92 | +information to existing probes. All probes are defined in |
| 93 | +[`src/common/dtrace_probes.d`](../../src/common/dtrace_probes.d). Usually their |
| 94 | +names of their module and the event that triggers them. To install Probes in C |
| 95 | +use the macros defined in `src/common/dtrace.h`. To fire a probe in the C code |
| 96 | +use the macro `DTRACEx`; where `x` is the number of arguments of the probe. |
| 97 | +There is also a macro `DTRACE_ENABLED`; its use allows for code to be only |
| 98 | +executed when a probe is enabled. |
| 99 | + |
| 100 | +### Adding a probe |
| 101 | + |
| 102 | +The first step to add a probe is to add its definition into |
| 103 | +[`src/common/dtrace_probes.d`](../../src/common/dtrace_probes.d). We have split |
| 104 | +the names of the probes into two parts: its category and the specific event. The |
| 105 | +name is split using `__`. We also add a comment to a probe explaining when it's |
| 106 | +fired and the information contained in its arguments. |
| 107 | + |
| 108 | +After adding the probe, we use it in the C code using the macros. Note that the |
| 109 | +split in the name is only a single underscore in the C code. The name of the |
| 110 | +probe should also be capitalised. We can call the probe defined as `gc__start` |
| 111 | +using the statement `DTRACE1(GC_START, scheduler)`. In this statement |
| 112 | +`scheduler` is the data used as the first argument. |
| 113 | + |
| 114 | +Then once the probe has been placed in all the appropriate places, we are ready |
| 115 | +to recompile. Make sure to use the DTrace flag while compiling. Recompiling will |
| 116 | +create the appropriate files using the system installation of DTrace. |
| 117 | + |
| 118 | +### Extending a probe |
| 119 | + |
| 120 | +We can extend a probe by adding an extra argument to the probe. Like adding a |
| 121 | +probe, the probe definition needs to be appended in |
| 122 | +[`src/common/dtrace_probes.d`](../../src/common/dtrace_probes.d). Note that this |
| 123 | +extra information needs to be available **everywhere** the probe is used. |
| 124 | + |
| 125 | +Once you've added the argument, you need to change **all** instances where the |
| 126 | +probe is in use. Note that you have to both add the new argument and change the |
| 127 | +`DTRACE` macro. Then you can recompile the PonyC compiler to use your new |
| 128 | +arguments. |
| 129 | + |
| 130 | +*Do not forget that if you change the order of the arguments for any of the |
| 131 | +existing nodes, you also need to change their usage in the example scripts.* |
0 commit comments