Conversation
Benchmark results for collatzParameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics. See unchanged results
|
Benchmark results for BadBoggleSolver_runParameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics. See unchanged results
|
|
Deploying to relenv to see what this yields |
341431b to
0e677ae
Compare
Mirrors TEST(DDProfPProf, aggregate) but drives the aggregation in a tight loop via google benchmark so we can measure ns/sample on the interned path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Exercises pprof_reset between two pprof_aggregate_interned_sample calls to confirm that the interned StringId2/FunctionId2/MappingId2 handles stored in the SymbolHdr-owned ProfilesDictionary remain valid across a profile reset and get serialized correctly on the second cycle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The libdatadog ProfilesDictionaryHandle is already a pointer type (ProfilesDictionary*), and the C API takes it by pointer-to-handle so it can out-write / zero the slot. The previous code heap-allocated that slot and wrapped it in a unique_ptr<Handle, Deleter> — effectively a smart pointer to a heap-allocated ProfilesDictionary** with no benefit. Introduce a small move-only RAII class that holds the handle inline. No behavior change; callers that need the pointer-to-handle the C API wants still get it via .get(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55f0990 to
a6eb45d
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6eb45d0f1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ddog_prof_Status status = ddog_prof_ProfilesDictionary_insert_str( | ||
| &string_id, dict, to_CharSlice(str), DDOG_PROF_UTF8_OPTION_ASSUME); |
There was a problem hiding this comment.
Validate strings before interning
When a profiled process has a mapped filename, debug source path, or symbol text containing non-UTF-8 bytes, this helper now passes that untrusted data to libdatadog with DDOG_PROF_UTF8_OPTION_ASSUME; libdatadog's ASSUME mode is documented/implemented as undefined behavior for invalid UTF-8 (it uses unchecked conversion), whereas the old Profile_add path validated strings. Use validate or lossy conversion here so arbitrary Linux path bytes cannot make the profiler invoke UB.
Useful? React with 👍 / 👎.
| Offset_t _offset{0}; | ||
| std::string _sopath; | ||
| BuildIdStr _build_id; | ||
| ddog_prof_Mapping2 *_mapping_id{nullptr}; |
There was a problem hiding this comment.
| ddog_prof_Mapping2 *_mapping_id{nullptr}; | |
| ddog_prof_MappingId2 _mapping_id{nullptr}; |
| explicit operator bool() const { return _handle != nullptr; } | ||
|
|
||
| // The C API expects a pointer-to-handle (so it can mutate the slot). | ||
| [[nodiscard]] const ddog_prof_ProfilesDictionaryHandle *get() const { |
There was a problem hiding this comment.
Not sure if this is necessary, the only used C API that requires a pointer-to-handle is ddog_prof_Profile_with_dictionary and it should not mutate the slot.
There was a problem hiding this comment.
I think this comment was about the get, I did not really adjust this, tell me if you feel strongly. I might have missed why this was important.
| Symbol make_symbol(std::string symname, const std::string &demangled_name, | ||
| uint32_t lineno, const std::string &srcpath, | ||
| const ddog_prof_ProfilesDictionary *dict) { | ||
| [[maybe_unused]] const std::string ignored_symname = std::move(symname); |
Move the storage to the libdatadog objects
|
@codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb1e5f2e65
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| DDRES_CHECK_FWD(pprof_create_profile( | ||
| ctx.worker_ctx.pprof[0], ctx, | ||
| ctx.worker_ctx.us->symbol_hdr._profiles_dictionary.get())); |
There was a problem hiding this comment.
Avoid sharing the intern dictionary across export buffers
When asynchronous export is used, both pprof buffers are created with this same SymbolHdr dictionary (and pprof[1] gets the same pointer just below). ddprof_worker_cycle then swaps buffers and starts ddprof_worker_export_thread to serialize the old profile while new samples continue aggregating into the other profile; those aggregations call pprof_aggregate_interned_sample and intern strings/functions/mappings into this shared dictionary. That defeats the existing double-buffering and leaves the exporter reading the dictionary concurrently with writes, which can corrupt serialized profiles or race in libdatadog. Use a per-buffer/export-snapshot dictionary or guard all serialization and interning with the same lock.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The key libdatadog header says ProfilesDictionary contains data common to multiple profiles, “whether that’s multiple profiles simultaneously or multiple profiles through time”, and that the current implementation is thread-safe. That matches our double-buffer setup: two Profiles sharing one long-lived SymbolHdr dictionary.
I think we are fine, though codex does not have access to the libdatadog APIs.
|
To answer a question, mappings are never cleared afaik, so we still partially rely on the hard worker reset. |
What does this PR do?
Switches the pprof pipeline to libdatadog's
ProfilesDictionaryso strings, functions, and mappings are interned once instead of copied per sample.Symbolstores aFunctionId2handle;MapInfoTableis nowvector<MappingId2>— no owned strings in either.CharSliceat sample time).Profile_add2on aProfile_with_dictionary-backed profile — no re-interning at sample time.ProfilesDictionaryheld bySymbolHdr(declared first, destroyed last, outlives all handles).MapInfoLookup) detects remaps at the same start address by reading identity back from the dictionary.Motivation
Copying stack symbol strings on every sample was the wrong design. Interned IDs let pprof aggregation be pointer-sized work.
How to test the change?
ddprof_pprof-utincludes a new aggregate → reset → aggregate cycle exercising ID stability acrosspprof_reset.mapinfo_lookup-utcovers cache hits, remap detection, build-id mismatch, pid isolation, and erase behaviour.pprof_aggregate-benchmicro-benchmark: on aarch64 Release, mean per-sample aggregation drops 877 ns → 333 ns (~2.6×).ddprof_exporter-utalready destroysSymbolHdrbefore serialization — covers dictionary-outliving-samples under ASan.