Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,6 @@ jobs:
restore-keys: |
gradle-caches-${{ runner.os }}-

- name: Cache async-profiler
uses: actions/cache@v4
with:
path: ddprof-lib/build/async-profiler
key: async-profiler-${{ runner.os }}-${{ hashFiles('gradle/lock.properties') }}
enableCrossOsArchive: true
restore-keys: |
async-profiler-${{ runner.os }}-

- name: Validate Javadoc
run: |
# Note: javadoc task depends on copyReleaseLibs which requires building native libraries
Expand Down
36 changes: 0 additions & 36 deletions .github/workflows/test_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,6 @@ jobs:
key: gradle-caches-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
gradle-caches-${{ runner.os }}-
- name: Cache async-profiler
if: steps.set_enabled.outputs.enabled == 'true'
uses: actions/cache@v4
with:
path: ddprof-lib/build/async-profiler
key: async-profiler-${{ runner.os }}-${{ hashFiles('gradle/lock.properties') }}
enableCrossOsArchive: true
restore-keys: |
async-profiler-${{ runner.os }}-
- name: Setup cached JDK
id: cache-jdk
if: steps.set_enabled.outputs.enabled == 'true'
Expand Down Expand Up @@ -173,15 +164,6 @@ jobs:
key: gradle-caches-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
gradle-caches-${{ runner.os }}-
- name: Cache async-profiler
if: steps.set_enabled.outputs.enabled == 'true'
uses: actions/cache@v4
with:
path: ddprof-lib/build/async-profiler
key: async-profiler-${{ runner.os }}-${{ hashFiles('gradle/lock.properties') }}
enableCrossOsArchive: true
restore-keys: |
async-profiler-${{ runner.os }}-
- name: Setup cached JDK
id: cache-jdk
uses: ./.github/actions/setup_cached_java
Expand Down Expand Up @@ -311,15 +293,6 @@ jobs:
with:
version: ${{ matrix.java_version }}
arch: 'aarch64'
- name: Cache async-profiler
if: steps.set_enabled.outputs.enabled == 'true'
uses: actions/cache@v4
with:
path: ddprof-lib/build/async-profiler
key: async-profiler-${{ runner.os }}-${{ hashFiles('gradle/lock.properties') }}
enableCrossOsArchive: true
restore-keys: |
async-profiler-${{ runner.os }}-
- name: Setup OS
if: steps.set_enabled.outputs.enabled == 'true'
run: |
Expand Down Expand Up @@ -427,15 +400,6 @@ jobs:
with:
version: ${{ matrix.java_version }}
arch: 'aarch64-musl'
- name: Cache async-profiler
if: steps.set_enabled.outputs.enabled == 'true'
uses: actions/cache@v4
with:
path: ddprof-lib/build/async-profiler
key: async-profiler-${{ runner.os }}-${{ hashFiles('gradle/lock.properties') }}
enableCrossOsArchive: true
restore-keys: |
async-profiler-${{ runner.os }}-
- name: Extract Versions
uses: ./.github/actions/extract_versions
- name: Test
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
.tmp
*.iml
/ddprof-stresstest/jmh-result.*
/ddprof-lib/src/main/cpp-external/**/*

**/.resources/

Expand Down
20 changes: 1 addition & 19 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,9 @@ The project supports multiple build configurations per platform:
- **asan**: AddressSanitizer build for memory error detection
- **tsan**: ThreadSanitizer build for thread safety validation

### Upstream Integration
The project maintains integration with async-profiler upstream:
- `cloneAsyncProfiler`: Clones DataDog's async-profiler fork
- `copyUpstreamFiles`: Copies selected upstream files to `ddprof-lib/src/main/cpp-external`
- `patchStackFrame`/`patchStackWalker`: Applies necessary patches for ASAN compatibility
- Lock file: `gradle/ap-lock.properties` specifies branch/commit

### Key Source Locations
- Java API: `ddprof-lib/src/main/java/com/datadoghq/profiler/JavaProfiler.java`
- C++ engine: `ddprof-lib/src/main/cpp/`
- Upstream C++ code: `ddprof-lib/src/main/cpp-external/` (generated)
- Native libraries: `ddprof-lib/build/lib/main/{config}/{os}/{arch}/`
- Test resources: `ddprof-test/src/test/java/`

Expand Down Expand Up @@ -221,9 +213,7 @@ The profiler uses a sophisticated double-buffered storage system for call traces
- **Buffer Management**: Thread-local recording buffers with configurable flush thresholds

### Native Integration Patterns
- **Upstream Sync**: Uses DataDog fork of async-profiler with branch `dd/master`
- **Adapter Pattern**: `*_dd.h` files adapt upstream code for Datadog needs
- **External Code**: Upstream files copied to `cpp-external/` with minimal patches
- **Signal Handler Safety**: Careful memory management in signal handler contexts

### Multi-Engine Profiling System
Expand Down Expand Up @@ -256,7 +246,7 @@ The profiler uses a sophisticated double-buffered storage system for call traces
### Code Organization Principles
- **Namespace Separation**: Use `ddprof` namespace for adapted upstream classes
- **File Naming**: Datadog adaptations use `*_dd` suffix (e.g., `stackWalker_dd.h`)
- **External Dependencies**: Upstream code in `cpp-external/`, local code in `cpp/`
- **External Dependencies**: Local code in `cpp/`

### Performance Constraints
- **Algorithmic Complexity**: Use O(N) or better, max 256 elements for linear scans
Expand All @@ -275,14 +265,6 @@ The profiler uses a sophisticated double-buffered storage system for call traces
- **Static Analysis**: `scanBuild` for additional code quality checks
- **Test Logging**: Use `TEST_LOG` macro for debug output in tests

### Upstream Integration Workflow
The project maintains a carefully managed relationship with async-profiler upstream:
1. **Lock File**: `gradle/ap-lock.properties` specifies exact upstream commit
2. **Branch Tracking**: `dd/master` branch contains safe upstream changes
3. **File Copying**: `copyUpstreamFiles` task selectively imports upstream code
4. **Minimal Patching**: Only essential patches for ASan compatibility
5. **Cherry-pick Strategy**: Rare cherry-picks only for critical fixes

## Build System Architecture

### Gradle Multi-project Structure
Expand Down
61 changes: 0 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,6 @@ cd java-profiler
The resulting artifact will be in `ddprof-lib/build/libs/ddprof-<version>.jar`

#### Gritty details
To smoothen the absorption of the upstream changes, we are using parts of the upstream codebase in (mostly) vanilla form.

For this, we have several gradle tasks in [ddprof-lib/build.gradle](ddprof-lib/build.gradle):
- `cloneAsyncProfiler` - clones the [DataDog/async-profiler](https://github.com/DataDog/async-profiler) repository into `ddprof-lib/build/async-profiler` using the commit lock specified in [gradle/lock.properties](gradle/lock.properties)
- in that repository, we are maintaining a branch called `dd/master` where we keep the upstream code in sync with the 'safe' changes from the upstream `master` branch
- cherry-picks into that branch should be rare and only done for critical fixes that are needed in the project
- otherwise, we should wait for the next upstream release to avoid conflicts
- `copyUpstreamFiles` - copies the selected upstream source files into the `ddprof-lib/src/main/cpp-external` directory
- `patchUpstreamFiles` - applies unified patches to upstream files for ASan compatibility, memory safety, and API extensions

Since the upstream code might not be 100% compatible with the current version of the project, we need to provide adapters.
The adapters are sharing the same file name as the upstream files but are suffixed with `_dd` (e.g. `arch_dd.h`).

Expand All @@ -55,57 +45,6 @@ conflicts with the upstream code. This allows us to use the upstream code as-is

See [ddprof-lib/src/main/cpp/stackWalker_dd.h](ddprof-lib/src/main/cpp/stackWalker_dd.h) for an example of how we adapt the upstream code to fit our needs.

### Unified Patching System

The project uses a unified configuration-driven patching system to apply modifications to upstream source files:

- **Configuration File**: All patches are defined in `gradle/patching.gradle` using structured Gradle DSL
- **Direct Source Modification**: Patches are applied directly to upstream source files using regex-based find/replace
- **Idempotent Operations**: Each patch includes checks to prevent double-application
- **Validation System**: Pre-patch validation ensures upstream structure hasn't changed incompatibly
- **Single Unified Task**: One `patchUpstreamFiles` task replaces multiple fragmented patch tasks

## Patch Configuration Structure

Patches are defined in `gradle/patching.gradle` with this structure:

```groovy
ext.upstreamPatches = [
"filename.cpp": [
validations: [
[contains: "expected_function"],
[contains: "expected_class"]
],
operations: [
[
type: "function_attribute",
name: "Add ASan compatibility attribute",
find: "(bool\\s+StackFrame::unwindStub\\s*\\()",
replace: "__attribute__((no_sanitize(\"address\"))) \$1",
idempotent_check: "__attribute__((no_sanitize(\"address\"))) bool StackFrame::unwindStub("
]
]
]
]
```

### Patch Operation Types

1. **function_attribute**: Add attributes (like `__attribute__`) to function declarations
2. **expression_replace**: Replace unsafe code patterns with safe equivalents
3. **method_declaration**: Add new method declarations to class definitions
4. **method_implementation**: Add complete method implementations to source files

### Adding New Patches

1. **Edit Configuration**: Add patch definition to `gradle/patching.gradle`
2. **Add Validations**: Ensure expected code structure exists
3. **Define Operations**: Specify find/replace patterns with appropriate type
4. **Include Idempotency**: Add `idempotent_check` to prevent double-application
5. **Test Thoroughly**: Verify patch works with clean upstream files

For detailed syntax documentation, see the comprehensive comments in `gradle/patching.gradle`.

## Claude Code Integration

This project includes Claude Code commands for streamlined development workflows when using [Claude Code](https://claude.ai/code):
Expand Down
3 changes: 0 additions & 3 deletions ddprof-lib/benchmarks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ application {

// Include the main library headers
tasks.withType(CppCompile).configureEach {
dependsOn ':ddprof-lib:patchUpstreamFiles'

includes file('../src/main/cpp').toString()
includes file('../src/main/cpp-external').toString()
}

// Add a task to run the benchmark
Expand Down
Loading
Loading