Skip to content
Open
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
10 changes: 8 additions & 2 deletions .github/workflows/prof_correctness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
export DD_PROFILING_EXCEPTION_MESSAGE_ENABLED=1
php -v
php -d extension=target/profiler-release/libdatadog_php_profiling.so --ri datadog-profiling
for test_case in "allocations" "time" "strange_frames" "timeline" "exceptions"; do
for test_case in "allocations" "time" "strange_frames" "timeline" "exceptions" "io"; do
mkdir -p profiling/tests/correctness/"$test_case"/
export DD_PROFILING_OUTPUT_PPROF=$PWD/profiling/tests/correctness/"$test_case"/test.pprof
php -d extension="${PWD}/target/profiler-release/libdatadog_php_profiling.so" "profiling/tests/correctness/${test_case}.php"
Expand All @@ -95,7 +95,7 @@ jobs:
export DD_PROFILING_EXCEPTION_MESSAGE_ENABLED=1
php -v
php -d extension=target/profiler-release/libdatadog_php_profiling.so --ri datadog-profiling
for test_case in "allocations" "time" "strange_frames" "timeline" "exceptions"; do
for test_case in "allocations" "time" "strange_frames" "timeline" "exceptions" "io"; do
mkdir -p profiling/tests/correctness/"$test_case"/
export DD_PROFILING_OUTPUT_PPROF=$PWD/profiling/tests/correctness/"$test_case"/test.pprof
php -d extension=$PWD/target/profiler-release/libdatadog_php_profiling.so profiling/tests/correctness/"$test_case".php
Expand Down Expand Up @@ -188,6 +188,12 @@ jobs:
expected_json: profiling/tests/correctness/allocation_time_combined.json
pprof_path: profiling/tests/correctness/allocation_time_combined/

- name: Check profiler correctness for IO
uses: Datadog/prof-correctness/analyze@main
with:
expected_json: profiling/tests/correctness/io.json
pprof_path: profiling/tests/correctness/io/

- name: Check profiler correctness for exceptions ZTS
if: matrix.phpts == 'zts'
uses: Datadog/prof-correctness/analyze@main
Expand Down
42 changes: 42 additions & 0 deletions profiling/src/profiling/sample_type_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,46 @@ mod tests {
);
assert_eq!(values, vec![10, 20, 30, 70]);
}

#[test]
fn filter_with_io_profiling() {
let mut settings = get_system_settings();
settings.profiling_enabled = true;
settings.profiling_io_enabled = true;

let sample_type_filter = SampleTypeFilter::new(&settings);
let values = sample_type_filter.filter(get_samples());
let types = sample_type_filter.sample_types();

assert_eq!(
types,
vec![
ValueType::new("sample", "count"),
ValueType::new("wall-time", "nanoseconds"),
ValueType::new("socket-read-time", "nanoseconds"),
ValueType::new("socket-read-time-samples", "count"),
ValueType::new("socket-write-time", "nanoseconds"),
ValueType::new("socket-write-time-samples", "count"),
ValueType::new("file-io-read-time", "nanoseconds"),
ValueType::new("file-io-read-time-samples", "count"),
ValueType::new("file-io-write-time", "nanoseconds"),
ValueType::new("file-io-write-time-samples", "count"),
ValueType::new("socket-read-size", "bytes"),
ValueType::new("socket-read-size-samples", "count"),
ValueType::new("socket-write-size", "bytes"),
ValueType::new("socket-write-size-samples", "count"),
ValueType::new("file-io-read-size", "bytes"),
ValueType::new("file-io-read-size-samples", "count"),
ValueType::new("file-io-write-size", "bytes"),
ValueType::new("file-io-write-size-samples", "count"),
]
);
assert_eq!(
values,
vec![
10, 20, 80, 81, 90, 91, 100, 101, 110, 111, 120, 121, 130,
131, 140, 141, 150, 151
]
);
}
}
36 changes: 36 additions & 0 deletions profiling/tests/correctness/io.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An error_margin of 10 is pretty high for this deterministic benchmark, isn't it? Any particular reason it isn't tighter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the runs and they all where at "0% error", but if we start adjusting the sampling distance, we might get some errors in the future.
I've tightened the error_margin to 2%. In case we see failures here when adjusting the sampling distance in the future, we can then make a decision of how to handle that.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"scale_by_duration": true,
"test_name": "php_io",
"stacks": [
{
"profile-type": "file-io-write-size",
"stack-content": [
{
"regular_expression": "<?php;main;big_write;standard\\|file_put_contents$",
"percent": 66,
"error_margin": 2
},
{
"regular_expression": "<?php;main;small_write;standard\\|file_put_contents$",
"percent": 33,
"error_margin": 2
}
]
},
{
"profile-type": "file-io-read-size",
"stack-content": [
{
"regular_expression": "<?php;main;big_read;standard\\|file_get_contents$",
"percent": 66,
"error_margin": 2
},
{
"regular_expression": "<?php;main;small_read;standard\\|file_get_contents$",
"percent": 33,
"error_margin": 2
}
]
}
]
}
50 changes: 50 additions & 0 deletions profiling/tests/correctness/io.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
// Test I/O profiling correctness.
//
// We write and read temporary files in known proportions to verify that
// file-io-write-size and file-io-read-size samples are captured correctly.
//
// Function `big_write` writes 2x more data than `small_write`, so we expect
// ~67% vs ~33% of file-io-write-size. Similarly for reads.
//
// The write functions return the file path so that read functions can reuse
// the same files without creating their own (which would pollute the write
// profile). Files are cleaned up in the main loop.

function big_write() {
$tmp = tempnam(sys_get_temp_dir(), 'io_test');
// Write 2MB
file_put_contents($tmp, str_repeat('A', 1024 * 1024 * 2));
return $tmp;
}

function small_write() {
$tmp = tempnam(sys_get_temp_dir(), 'io_test');
// Write 1MB
file_put_contents($tmp, str_repeat('B', 1024 * 1024));
return $tmp;
}

function big_read($path) {
// Read 2MB
file_get_contents($path, false, null, 0, 1024 * 1024 * 2);
}

function small_read($path) {
// Read 1MB
file_get_contents($path, false, null, 0, 1024 * 1024);
}

function main() {
$duration = $_ENV["EXECUTION_TIME"] ?? 10;
$end = microtime(true) + $duration;
while (microtime(true) < $end) {
$big = big_write();
$small = small_write();
big_read($big);
small_read($small);
unlink($big);
unlink($small);
}
}
main();
Loading