This shows you the differences between two versions of the page.
ep:labs:07:contents:tasks:ex2 [2025/05/05 00:37] radu.mantu |
ep:labs:07:contents:tasks:ex2 [2025/05/05 00:58] (current) radu.mantu |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ==== 02. [??p] Simple function instrumentation ==== | + | ==== 02. [30p] Simple function instrumentation ==== |
Normally, static instrumentation has a steep learning curve and requires some prior knowledge of how compilers work. | Normally, static instrumentation has a steep learning curve and requires some prior knowledge of how compilers work. | ||
Line 17: | Line 17: | ||
If you wish to learn more about static instrumentation we recommend this [[https://gabrieleserra.ml/blog/2020-08-27-an-introduction-to-gcc-and-gccs-plugins.html|blog post]] that is one of the few good resources available for **gcc**. Although **llvm** is more popular for developing instrumentation / optimization passes, their API is a clusterfuck that changes every few months. **gcc** is more stable and does not require you to recompile the whole compiler in order to use them transparently. In contrast, the current pass manager in **llvm** can only load passes implemented as shared object plugins via **opt** (i.e., the **llvm** optimizer) which only works on llvm bitcode. | If you wish to learn more about static instrumentation we recommend this [[https://gabrieleserra.ml/blog/2020-08-27-an-introduction-to-gcc-and-gccs-plugins.html|blog post]] that is one of the few good resources available for **gcc**. Although **llvm** is more popular for developing instrumentation / optimization passes, their API is a clusterfuck that changes every few months. **gcc** is more stable and does not require you to recompile the whole compiler in order to use them transparently. In contrast, the current pass manager in **llvm** can only load passes implemented as shared object plugins via **opt** (i.e., the **llvm** optimizer) which only works on llvm bitcode. | ||
- | === [??p] Task A - HTTP client instrumentation === | + | === [10p] Task A - HTTP client instrumentation === |
In the [[https://github.com/cs-pub-ro/EP-labs|code skeleton]] for this lab, you will find an example application that performs an HTTP GET request and displays the response. With this application, we've also included an example implementation of instrumentation callbacks. Try to compile both of these and run the instrumented TCP client. | In the [[https://github.com/cs-pub-ro/EP-labs|code skeleton]] for this lab, you will find an example application that performs an HTTP GET request and displays the response. With this application, we've also included an example implementation of instrumentation callbacks. Try to compile both of these and run the instrumented TCP client. | ||
Line 44: | Line 44: | ||
Take a moment to analyze the source code and Makefile, then move on to the next task. | Take a moment to analyze the source code and Makefile, then move on to the next task. | ||
- | === [??p] Task B - Elapsed time measurement === | + | === [20p] Task B - Elapsed time measurement === |
Time to get your hands dirty! Modify the instrumentation callbacks in a way that will allow you to measure the time spent in each function. In other words, measure the elapsed time between entering and exiting a function. | Time to get your hands dirty! Modify the instrumentation callbacks in a way that will allow you to measure the time spent in each function. In other words, measure the elapsed time between entering and exiting a function. | ||
Line 51: | Line 51: | ||
Add a [[https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html|destructor]] to the instrumentation callback library in which you will display these statistics when the program terminates. | Add a [[https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html|destructor]] to the instrumentation callback library in which you will display these statistics when the program terminates. | ||
+ | |||
+ | <note tip> | ||
+ | If you are working natively on Linux, consider using the **rdtsc** macro from ''util.h''. This is a wrapper over the [[https://www.felixcloutier.com/x86/rdtsc|RDTSC]] instruction and it's the most efficient method of calculating the elapsed time. You can find a usage example [[https://github.com/RaduMantu/tsn-keysight/blob/master/src/slice.c#L22|here]]. Keep in mind that your CPU increments this timestamp counter a fixed number of times per second. This frequency is also the //base frequency// of your CPU. You can find it expressed in kHz in ''/sys/devices/system/cpu/cpu0/cpufreq/base_frequency''. | ||
+ | |||
+ | If you are working inside a VM or simply don't want to use **rdtsc**, use [[https://linux.die.net/man/3/clock_gettime|clock_gettime()]] instead. Choose a //monotonic timer// that fits your needs. Check each timer's resolution and explain why it matters. | ||
+ | </note> |