Skip to content

Commit

Permalink
perf: reduce memory usage in profiling
Browse files Browse the repository at this point in the history
Utilizes ThinStr in the ZendFrame to shrink memory.

perf: pre-calculate buffer size in stalk walking
  • Loading branch information
morrisonlevi committed Jan 13, 2025
1 parent b0171fa commit e49f49a
Show file tree
Hide file tree
Showing 10 changed files with 532 additions and 363 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions profiling/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ chrono = { version = "0.4" }
crossbeam-channel = { version = "0.5", default-features = false, features = ["std"] }
datadog-alloc = { git = "https://github.com/DataDog/libdatadog", tag = "v10.0.0" }
datadog-profiling = { git = "https://github.com/DataDog/libdatadog", tag = "v10.0.0" }
datadog-thin-str = { version = "1", path = "../thin-str", features = ["std"] }
ddcommon = { git = "https://github.com/DataDog/libdatadog", tag = "v10.0.0" }
env_logger = { version = "0.11", default-features = false }
indexmap = { version = "2.2" }
Expand All @@ -47,6 +48,10 @@ perfcnt = "0.8.0"
name = "stack_walking"
harness = false

[[bench]]
name = "concatenation"
harness = false

[features]
default = ["allocation_profiling", "timeline", "exception_profiling"]
allocation_profiling = []
Expand Down
83 changes: 83 additions & 0 deletions profiling/benches/concatenation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use criterion::{criterion_group, criterion_main, Criterion};

#[allow(unused)]
fn extract_function_name_v1(module_name: &[u8], class_name: &[u8], method_name: &[u8]) -> Vec<u8> {
let mut buffer = Vec::<u8>::new();

if !module_name.is_empty() {
buffer.extend_from_slice(module_name);
buffer.push(b'|');
}

if !class_name.is_empty() {
buffer.extend_from_slice(class_name);
buffer.extend_from_slice(b"::");
}
buffer.extend_from_slice(method_name);
buffer
}

#[allow(unused)]
fn extract_function_name_v2(module_name: &[u8], class_name: &[u8], method_name: &[u8]) -> Vec<u8> {
let opt_module_separator: &[u8] = if module_name.is_empty() { b"" } else { b"|" };
let opt_class_separator: &[u8] = if class_name.is_empty() { b"" } else { b"::" };
let cap = module_name.len()
+ opt_module_separator.len()
+ class_name.len()
+ opt_class_separator.len()
+ method_name.len();
let mut buffer = Vec::<u8>::with_capacity(cap);

buffer.extend_from_slice(module_name);
buffer.extend_from_slice(opt_module_separator);
buffer.extend_from_slice(class_name);
buffer.extend_from_slice(opt_class_separator);
buffer.extend_from_slice(method_name);
buffer
}

fn bench_concatenation_userland(c: &mut Criterion) {
c.bench_function("bench_concatenation_userland", |b| {
b.iter(|| {
for _ in 1..=100 {
_ = std::hint::black_box(extract_function_name_v2(
b"",
b"Twig\\Template",
b"displayWithErrorHandling",
))
}
});
});
}

fn bench_concatenation_internal1(c: &mut Criterion) {
c.bench_function("bench_concatenation_internal1", |b| {
b.iter(|| {
for _ in 1..=100 {
_ = std::hint::black_box(extract_function_name_v2(
b"dom",
b"DOMDocumentFragment",
b"__construct",
))
}
});
});
}

fn bench_concatenation_internal2(c: &mut Criterion) {
c.bench_function("bench_concatenation_internal2", |b| {
b.iter(|| {
for _ in 1..=100 {
_ = std::hint::black_box(extract_function_name_v2(b"standard", b"", b"file"))
}
});
});
}

criterion_group!(
benches,
bench_concatenation_userland,
bench_concatenation_internal1,
bench_concatenation_internal2,
);
criterion_main!(benches);
4 changes: 2 additions & 2 deletions profiling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ mod logging;
mod pcntl;
pub mod profiling;
mod sapi;
mod thin_str;
mod wall_time;
mod well_known;

#[cfg(php_run_time_cache)]
mod string_set;
Expand Down Expand Up @@ -313,7 +313,7 @@ extern "C" fn minit(_type: c_int, module_number: c_int) -> ZendResult {
};

/* Currently, the engine is always copying this struct. Every time a new
* PHP version is released, we should double check zend_register_extension
* PHP version is released, we should double-check zend_register_extension
* to ensure the address is not mutated nor stored. Well, hopefully we
* catch it _before_ a release.
*/
Expand Down
Loading

0 comments on commit e49f49a

Please sign in to comment.