mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 05:10:49 +00:00
Bug 1735397 - mozilla::profiler::detail::FilterHasPid and FiltersExcludePid - r=florian
These will be used to check special thread filter rules around "pid:..." filters. Differential Revision: https://phabricator.services.mozilla.com/D135853
This commit is contained in:
parent
7e96f5a4d3
commit
ca8a203ae8
@ -6,8 +6,87 @@
|
||||
|
||||
#include "mozilla/BaseAndGeckoProfilerDetail.h"
|
||||
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
|
||||
namespace mozilla::profiler::detail {
|
||||
|
||||
; // TODO Add code here.
|
||||
constexpr std::string_view scPidPrefix = "pid:";
|
||||
|
||||
// Convert a C string to a BaseProfilerProcessId. Return unspecified
|
||||
// BaseProfilerProcessId if the string is not exactly a valid pid.
|
||||
static baseprofiler::BaseProfilerProcessId StringToPid(const char* aString) {
|
||||
if (!aString || aString[0] == '\0') {
|
||||
// Null or empty.
|
||||
return baseprofiler::BaseProfilerProcessId{};
|
||||
}
|
||||
|
||||
if (aString[0] == '0') {
|
||||
if (aString[1] != '\0') {
|
||||
// Don't accept leading zeroes.
|
||||
return baseprofiler::BaseProfilerProcessId{};
|
||||
}
|
||||
return baseprofiler::BaseProfilerProcessId::FromNumber(0);
|
||||
}
|
||||
|
||||
using PidNumber = baseprofiler::BaseProfilerProcessId::NumberType;
|
||||
PidNumber pid = 0;
|
||||
for (;;) {
|
||||
const char c = *aString;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
if (c < '0' || c > '9') {
|
||||
// Only accept decimal digits.
|
||||
return baseprofiler::BaseProfilerProcessId{};
|
||||
}
|
||||
static_assert(!std::numeric_limits<PidNumber>::is_signed,
|
||||
"The following relies on unsigned arithmetic");
|
||||
PidNumber newPid = pid * 10u + PidNumber(c - '0');
|
||||
if (newPid < pid) {
|
||||
// Unsigned overflow.
|
||||
return baseprofiler::BaseProfilerProcessId{};
|
||||
}
|
||||
pid = newPid;
|
||||
++aString;
|
||||
}
|
||||
return baseprofiler::BaseProfilerProcessId::FromNumber(pid);
|
||||
}
|
||||
|
||||
[[nodiscard]] MFBT_API bool FilterHasPid(
|
||||
const char* aFilter, baseprofiler::BaseProfilerProcessId aPid) {
|
||||
if (strncmp(aFilter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
|
||||
// The filter is not starting with "pid:".
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringToPid(aFilter + scPidPrefix.length()) == aPid;
|
||||
}
|
||||
|
||||
[[nodiscard]] MFBT_API bool FiltersExcludePid(
|
||||
Span<const char* const> aFilters,
|
||||
baseprofiler::BaseProfilerProcessId aPid) {
|
||||
if (aFilters.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, check if the list only contains "pid:..." strings.
|
||||
for (const char* const filter : aFilters) {
|
||||
if (strncmp(filter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
|
||||
// At least one filter is *not* a "pid:...", our pid is not excluded.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Here, all filters start with "pid:". Check if the given pid is included.
|
||||
for (const char* const filter : aFilters) {
|
||||
if (StringToPid(filter + scPidPrefix.length()) == aPid) {
|
||||
// Our pid is present, so it's not excluded.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Our pid was not in a list of only pids, so it's excluded.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla::profiler::detail
|
||||
|
@ -13,9 +13,30 @@
|
||||
#ifndef BaseAndGeckoProfilerDetail_h
|
||||
#define BaseAndGeckoProfilerDetail_h
|
||||
|
||||
#include "mozilla/BaseProfilerUtils.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
namespace mozilla::profiler::detail {
|
||||
|
||||
; // TODO Add APIs here.
|
||||
// True if the filter is exactly "pid:<aPid>".
|
||||
[[nodiscard]] MFBT_API bool FilterHasPid(
|
||||
const char* aFilter, baseprofiler::BaseProfilerProcessId aPid =
|
||||
baseprofiler::profiler_current_process_id());
|
||||
|
||||
// Only true if the filters only contain "pid:..." strings, and *none* of them
|
||||
// is exactly "pid:<aPid>". E.g.:
|
||||
// - [], 123 -> false (no pids)
|
||||
// - ["main"], 123 -> false (not all pids)
|
||||
// - ["main", "pid:123"], 123 -> false (not all pids)
|
||||
// - ["pid:123"], 123 -> false (all pids, including "pid:123")
|
||||
// - ["pid:123", "pid:456"], 123 -> false (all pids, including "pid:123")
|
||||
// - ["pid:456"], 123 -> true (all pids, but no "pid:123")
|
||||
// - ["pid:456", "pid:789"], 123 -> true (all pids, but no "pid:123")
|
||||
[[nodiscard]] MFBT_API bool FiltersExcludePid(
|
||||
Span<const char* const> aFilters,
|
||||
baseprofiler::BaseProfilerProcessId aPid =
|
||||
baseprofiler::profiler_current_process_id());
|
||||
|
||||
} // namespace mozilla::profiler::detail
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "BaseProfiler.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/BaseAndGeckoProfilerDetail.h"
|
||||
#include "mozilla/BaseProfileJSONWriter.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/ProgressLogger.h"
|
||||
@ -229,6 +230,92 @@ void TestProfilerUtils() {
|
||||
printf("TestProfilerUtils done\n");
|
||||
}
|
||||
|
||||
void TestBaseAndProfilerDetail() {
|
||||
printf("TestBaseAndProfilerDetail...\n");
|
||||
|
||||
{
|
||||
using mozilla::profiler::detail::FilterHasPid;
|
||||
|
||||
const auto pid123 =
|
||||
mozilla::baseprofiler::BaseProfilerProcessId::FromNumber(123);
|
||||
MOZ_RELEASE_ASSERT(FilterHasPid("pid:123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid(" ", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid=123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:123 ", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid: 123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:0123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:0000000000000000000000123", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:12", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:1234", pid123));
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid("pid:0", pid123));
|
||||
|
||||
using PidNumber = mozilla::baseprofiler::BaseProfilerProcessId::NumberType;
|
||||
const PidNumber maxNumber = std::numeric_limits<PidNumber>::max();
|
||||
const auto maxPid =
|
||||
mozilla::baseprofiler::BaseProfilerProcessId::FromNumber(maxNumber);
|
||||
const std::string maxPidString = "pid:" + std::to_string(maxNumber);
|
||||
MOZ_RELEASE_ASSERT(FilterHasPid(maxPidString.c_str(), maxPid));
|
||||
|
||||
const std::string tooBigPidString = maxPidString + "0";
|
||||
MOZ_RELEASE_ASSERT(!FilterHasPid(tooBigPidString.c_str(), maxPid));
|
||||
}
|
||||
|
||||
{
|
||||
using mozilla::profiler::detail::FiltersExcludePid;
|
||||
const auto pid123 =
|
||||
mozilla::baseprofiler::BaseProfilerProcessId::FromNumber(123);
|
||||
|
||||
MOZ_RELEASE_ASSERT(
|
||||
!FiltersExcludePid(mozilla::Span<const char*>{}, pid123));
|
||||
|
||||
{
|
||||
const char* const filters[] = {"main"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"main", "pid:123"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"main", "pid:456"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"pid:123"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"pid:123", "pid:456"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"pid:456", "pid:123"};
|
||||
MOZ_RELEASE_ASSERT(!FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"pid:456"};
|
||||
MOZ_RELEASE_ASSERT(FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
|
||||
{
|
||||
const char* const filters[] = {"pid:456", "pid:789"};
|
||||
MOZ_RELEASE_ASSERT(FiltersExcludePid(filters, pid123));
|
||||
}
|
||||
}
|
||||
|
||||
printf("TestBaseAndProfilerDetail done\n");
|
||||
}
|
||||
|
||||
void TestProportionValue() {
|
||||
printf("TestProportionValue...\n");
|
||||
|
||||
@ -5129,6 +5216,7 @@ int main()
|
||||
#endif // MOZ_GECKO_PROFILER
|
||||
|
||||
TestProfilerUtils();
|
||||
TestBaseAndProfilerDetail();
|
||||
TestProportionValue();
|
||||
TestProgressLogger();
|
||||
// Note that there are two `TestProfiler{,Markers}` functions above, depending
|
||||
|
Loading…
x
Reference in New Issue
Block a user