| 
 | 1 | +# Profiling Tools  | 
 | 2 | + | 
 | 3 | +This document explains the profiling infrastructure set up for our indexer-service and tap-agent services. The profiling setup enables developers to diagnose performance issues, memory leaks, and analyze runtime behavior in both development and production environments.  | 
 | 4 | + | 
 | 5 | +## Overview  | 
 | 6 | + | 
 | 7 | +Our project includes an integrated profiling system for the indexer services. The system supports multiple profiling methods through:  | 
 | 8 | + | 
 | 9 | +1. A custom `profiler` library (included in the workspace)  | 
 | 10 | +2. Docker-based profiling environments  | 
 | 11 | +3. Various third-party profiling tools  | 
 | 12 | + | 
 | 13 | +## Available Profiling Methods  | 
 | 14 | + | 
 | 15 | +### Built-in Profiler (pprof-based Flamegraphs)  | 
 | 16 | + | 
 | 17 | +A Rust library that uses [pprof](https://crates.io/crates/pprof) to continuously profile the application and generate flamegraphs at specified intervals.  | 
 | 18 | +This solution was particularly suitable because tools like `perf`, while powerful, often pose configuration challenges or require specific capabilities (like CAP_SYS_ADMIN) that complicate their deployment within standard Docker containers.  | 
 | 19 | + | 
 | 20 | +- **Configuration**: Set in code with the `setup_profiling` function  | 
 | 21 | +- **Activation**: Enabled via the `profiling` feature flag  | 
 | 22 | +- **Output**: Flamegraphs (SVG) and protobuf profiles in `/opt/profiling/{service-name}/`  | 
 | 23 | + | 
 | 24 | +### External Profiling Tools  | 
 | 25 | + | 
 | 26 | +The profiling environment also supports the following tools:  | 
 | 27 | + | 
 | 28 | +| Tool          | Description                              | Output                                        |  | 
 | 29 | +| ------------- | ---------------------------------------- | --------------------------------------------- |  | 
 | 30 | +| **strace**    | Traces system calls with detailed timing | `/opt/profiling/{service-name}/strace.log`    |  | 
 | 31 | +| **valgrind**  | Memory profiling with Massif             | `/opt/profiling/{service-name}/massif.out`    |  | 
 | 32 | +| **callgrind** | CPU profiling (part of valgrind)         | `/opt/profiling/{service-name}/callgrind.out` |  | 
 | 33 | + | 
 | 34 | +## How to Use  | 
 | 35 | + | 
 | 36 | +### Prerequisites  | 
 | 37 | + | 
 | 38 | +Run the setup command first to prepare the testing environment:  | 
 | 39 | + | 
 | 40 | +```bash  | 
 | 41 | +just setup  | 
 | 42 | +```  | 
 | 43 | + | 
 | 44 | +### Profiling Commands  | 
 | 45 | + | 
 | 46 | +Use the following commands to profile specific services:  | 
 | 47 | + | 
 | 48 | +```bash  | 
 | 49 | +# Profile with flamegraph (default)  | 
 | 50 | +just profile-flamegraph  | 
 | 51 | + | 
 | 52 | +# Profile with valgrind  | 
 | 53 | +just profile-valgrind  | 
 | 54 | + | 
 | 55 | +# Profile with strace  | 
 | 56 | +just profile-strace  | 
 | 57 | + | 
 | 58 | +# Profile with callgrind  | 
 | 59 | +just profile-callgrind  | 
 | 60 | + | 
 | 61 | +# Stop profiling (gracefully terminate to generate output)  | 
 | 62 | +just stop-profiling  | 
 | 63 | + | 
 | 64 | +# Restore normal service without profiling  | 
 | 65 | +just profile-restore  | 
 | 66 | +```  | 
 | 67 | + | 
 | 68 | +### Viewing Results  | 
 | 69 | + | 
 | 70 | +Profiling data is stored in:  | 
 | 71 | + | 
 | 72 | +- `contrib/profiling/indexer-service/`  | 
 | 73 | +- `contrib/profiling/tap-agent/`  | 
 | 74 | + | 
 | 75 | +#### Visualization Tools  | 
 | 76 | + | 
 | 77 | +- **Flamegraphs**: Open the SVG files in any web browser  | 
 | 78 | +- **Callgrind**: Use `callgrind_annotate` or KCachegrind for visualization:  | 
 | 79 | + | 
 | 80 | +  ```bash  | 
 | 81 | +  callgrind_annotate contrib/profiling/tap-agent/callgrind.out  | 
 | 82 | +  ```  | 
 | 83 | + | 
 | 84 | +- **Massif**: Use `ms_print` to view memory profiling results:  | 
 | 85 | + | 
 | 86 | +  ```bash  | 
 | 87 | +  ms_print contrib/profiling/tap-agent/massif.out  | 
 | 88 | +  ```  | 
 | 89 | + | 
 | 90 | +- **Protobuf Profiles**: View with Go pprof tools:  | 
 | 91 | + | 
 | 92 | +```go  | 
 | 93 | +# Install Go pprof tools if needed  | 
 | 94 | +go install github.com/google/pprof@latest  | 
 | 95 | + | 
 | 96 | +# View interactive web UI (most user-friendly)  | 
 | 97 | +pprof -http=:8080 contrib/profiling/indexer-service/profile-*.pb  | 
 | 98 | + | 
 | 99 | +# Or generate a flamegraph from protobuf data  | 
 | 100 | +pprof -flamegraph contrib/profiling/indexer-service/profile-*.pb > custom_flamegraph.svg  | 
 | 101 | +```  | 
 | 102 | + | 
 | 103 | +## Implementation Details  | 
 | 104 | + | 
 | 105 | +### Profiler Integration  | 
 | 106 | + | 
 | 107 | +The profiler library is conditionally compiled using the `profiling` feature flag:  | 
 | 108 | + | 
 | 109 | +```rust  | 
 | 110 | +#[cfg(feature = "profiling")]  | 
 | 111 | +if let Err(e) = profiler::setup_profiling(  | 
 | 112 | +    "/opt/profiling/indexer-service".to_string(),  | 
 | 113 | +    150,    // sampling frequency (Hz)  | 
 | 114 | +    120,    // interval between reports (seconds)  | 
 | 115 | +    Some("Indexer Service".to_string()),  | 
 | 116 | +) {  | 
 | 117 | +    tracing::error!("Failed to setup profiling: {e}");  | 
 | 118 | +} else {  | 
 | 119 | +    tracing::info!("Profiling setup complete.");  | 
 | 120 | +}  | 
 | 121 | +```  | 
 | 122 | + | 
 | 123 | +### Docker Environment  | 
 | 124 | + | 
 | 125 | +The profiling infrastructure uses a custom Docker image with all necessary tools pre-installed. The container runs with elevated privileges to support profiling:  | 
 | 126 | + | 
 | 127 | +```yaml  | 
 | 128 | +cap_add:  | 
 | 129 | +  - SYS_ADMIN  | 
 | 130 | +privileged: true  | 
 | 131 | +security_opt:  | 
 | 132 | +  - seccomp:unconfined  | 
 | 133 | +```  | 
 | 134 | +
  | 
 | 135 | +## Notes  | 
 | 136 | +
  | 
 | 137 | +- The flamegraph profiling is enabled whenever using any of the profiling commands through the Justfile, as the binaries are compiled with the `profiling` feature flag.  | 
 | 138 | +- For production use, prefer the built-in profiler over the external tools to minimize performance impact.  | 
 | 139 | +- When using callgrind, consider enabling debug information and frame pointers in your Cargo.toml for better output:  | 
 | 140 | + | 
 | 141 | +  ```toml  | 
 | 142 | +  [profile.release]  | 
 | 143 | +  debug = true  | 
 | 144 | +  force-frame-pointers = true  | 
 | 145 | +  ```  | 
0 commit comments