This is a profiler-specific shared lock (aka readers-writer lock) implemented on top of RWLockImpl.
Similar to BaseProfilerMutex, it records which thread is currently holding the exclusive lock.
Differential Revision: https://phabricator.services.mozilla.com/D139916
This is a profiler-specific shared lock (aka readers-writer lock) implemented on top of RWLockImpl.
Similar to BaseProfilerMutex, it records which thread is currently holding the exclusive lock.
Differential Revision: https://phabricator.services.mozilla.com/D139916
Add `ProgressLogger` parameter to most JSON-generating functions.
Each function can update the given `ProgressLogger` between 0% and 100%, and create sub-loggers when calling functions.
The main goal of this instrumentation is to notice when any progress is made by child processes (when the parent process is gathering profiles), so it needs to go deep enough so that it is not stuck on a progress value for "too long" -- During development, that meant progress was always happening when observed every 10ms; In later patches, the overall timeout for no-progress-made will be at least 1 second.
Differential Revision: https://phabricator.services.mozilla.com/D135479
Class storing a value between 0 and 1, effectively 0% to 100%.
It will be used through a ProgressLogger object to track the progress of JSON profile generation (see following patches).
Differential Revision: https://phabricator.services.mozilla.com/D135477
Previously, DeserializeAfterKindAndStream would take a JSON writer and a thread id, using the thread id (if specified) to only output markers from that thread to the given writer.
Now, DeserializeAfterKindAndStream takes a lambda, which will be called with the thread id found in the marker, that lambda can either return null (nothing to output) or a pointer to a writer, in which case the marker is read and output to the given writer.
This makes DeserializeAfterKindAndStream more flexible, and will allow handling markers from different threads, each possibly being output to different writers.
Also, for simplicity the entry is now always fully read, so there is no need for the caller to do anything. The return bool is therefore unnecessary, and has been removed.
Differential Revision: https://phabricator.services.mozilla.com/D128433
If the profiler is paused, then really, threads are not *being* profiled.
profiler_is_active_and_unpaused() was added, to help with non-MOZ_GECKO_PROFILER builds.
(Note: baseprofiler::profiler_thread_is_being_profiled(ProfilerThreadId) is not possible to implement, but it's not needed anyway.)
Differential Revision: https://phabricator.services.mozilla.com/D128707
Because string contents could be split in two separate chunks, the default ProfilerStringView deserializer needed to concatenate it together in an off-chunk buffer.
But now thanks to ProfileBufferEntryReader::ReadSpans, it is possible to know if the contents are in a single memory area inside one chunk (which should be the vast majority of cases), in which case the ProfilerStringView can just reference it using its internal std::string_view, which saves managing a separate buffer and copying data into it.
However this can only be done safely when the span is correctly aligned for the character type, which may not be the case for char16_t strings that must be even-aligned.
Differential Revision: https://phabricator.services.mozilla.com/D124430
`ProfilerStringView::Data()` would return a pointer to the start of the string, but there may not be a null terminator at the end!
To reduce the likelihood of misuses, that function has now been removed.
Instead, callers must now access the data through `AsSpan` or the `Span` conversion operator (which makes it easy to use with `NS_ConvertUTF16toUTF8` for example).
It was not an issue until now, because deserialized string would always be terminated when copied out of the profile buffer, but a following patch will add optimized code where the non-terminated string inside the buffer will be directly pointed at.
Differential Revision: https://phabricator.services.mozilla.com/D125027
Because string contents could be split in two separate chunks, the default ProfilerStringView deserializer needed to concatenate it together in an off-chunk buffer.
But now thanks to ProfileBufferEntryReader::ReadSpans, it is possible to know if the contents are in a single memory area inside one chunk (which should be the vast majority of cases), in which case the ProfilerStringView can just reference it using its internal std::string_view, which saves managing a separate buffer and copying data into it.
However this can only be done safely when the span is correctly aligned for the character type, which may not be the case for char16_t strings that must be even-aligned.
Differential Revision: https://phabricator.services.mozilla.com/D124430
Because string contents could be split in two separate chunks, the default ProfilerStringView deserializer needed to concatenate it together in an off-chunk buffer.
But now thanks to ProfileBufferEntryReader::ReadSpans, it is possible to know if the contents are in a single memory area inside one chunk (which should be the vast majority of cases), in which case the ProfilerStringView can just reference it using its internal std::string_view, which saves managing a separate buffer and copying data into it.
Differential Revision: https://phabricator.services.mozilla.com/D124430
Instead of blindly outputting floating-point numbers of milliseconds, which leads to things like 363.03499999999997, times in ms are now converted to integer number of nanoseconds, stringified, and then manually adjusted to milliseconds again, so we get smaller and friendlier outputs like 363.035.
Eventually, bug 1726675 may change all times to integer number of nanoseconds anyway, but this patch is already helpful in reducing the output, and paves the way by separating the time-output functions from other number outputs.
Differential Revision: https://phabricator.services.mozilla.com/D123329
This hides the scProfilerMainThreadId detail, and makes for a safer API.
Also, ::profiler_init_main_thread_id() calls ::mozilla::baseprofiler::profiler_init_main_thread_id().
And in non-MOZ_GECKO_PROFILER builds, AUTO_PROFILER_INIT calls profiler_init_main_thread_id(), which makes other main-thread functions usable there (assuming profiler_current_thread_id works).
Differential Revision: https://phabricator.services.mozilla.com/D121695
This patch only shuffles source code around, so that all declarations in {,Base}ProfilerUtils.h are now implemented only in ProfilerUtils.cpp (instead of the different platform-*.cpp), the final generated code should be the same in MOZ_GECKO_PROFILER builds (the default on all our supported platforms).
This simplifies the headers and makes further changes easier.
In non-MOZ_GECKO_PROFILER builds: On supported platforms these functions are now fully defined; Unsupported platforms should all had `getpid()`, but thread ids are null.
So now `profiler_current_process_id()` is available on all platforms, at all tier levels.
Differential Revision: https://phabricator.services.mozilla.com/D121051
Since ProfilerProcessId and ProfilerThreadId (and their NumberTypes) will potentially grow to 64 bits on some platforms (in a later patch), all code that uses them must be able to handle bigger types.
Differential Revision: https://phabricator.services.mozilla.com/D121049
These classes should replace the `int` type that is currently used to store process and thread ids. The next patches will start using them. Advantages:
- Prevent type mismatches, e.g., giving a process id (or other number) to a function expecting a thread id.
- Prevent nonsensical arithmetic operations.
- Make the unspecified id more abstract, so it's more obvious and portable.
- Make conversions to/from numbers (for display or storage) more visible.
- Allow future changes of APIs using them less risky.
- Allow future changes of the ids themselves (e.g., to be able to use bigger underlying types on some platforms, or even the opaque std:🧵:id type.)
Differential Revision: https://phabricator.services.mozilla.com/D120221
Instead of discarding released chunks, we keep them as "next" chunks, and we make sure there's a valid "current" chunk when possible.
Recycling released chunks means that when using the `ProfileBufferChunkManagerSingle`, the one chunk, in whichever state it may be, will be kept alive and reused.
Differential Revision: https://phabricator.services.mozilla.com/D99979
When a "Put" operation fails (most probably because no chunk was available to store the data), we remember the number of bytes that couldn't be stored.
This can be useful to give an indication of how much more memory would have been needed for successful puts.
Differential Revision: https://phabricator.services.mozilla.com/D99977
This bug has revealed some issues when the single chunk gets filled, and there are different paths depending on whether the chunk is filled right to the end, or past it.
Later patches will fix these issues and update these tests accordingly.
Differential Revision: https://phabricator.services.mozilla.com/D99976