Add Perfetto Tracing to NCE Trapping API

As a performance sensitive part of code, the NCE Trapping API benefits from having tracing and it helps us better determine where guest code is spending its time for more targeted optimizations.
This commit is contained in:
PixelyIon 2022-07-26 19:35:47 +05:30
parent 9d294b9ccc
commit 1af781c0a5
No known key found for this signature in database
GPG Key ID: 11BC6C3201BC2C05
4 changed files with 18 additions and 0 deletions

View File

@ -12,6 +12,7 @@ PERFETTO_DEFINE_CATEGORIES(
perfetto::Category("scheduler").SetDescription("Events from the HLE scheduler"), perfetto::Category("scheduler").SetDescription("Events from the HLE scheduler"),
perfetto::Category("kernel").SetDescription("Events from parts of the HLE kernel"), perfetto::Category("kernel").SetDescription("Events from parts of the HLE kernel"),
perfetto::Category("guest").SetDescription("Events relating to guest code"), perfetto::Category("guest").SetDescription("Events relating to guest code"),
perfetto::Category("host").SetDescription("Events relating to host code"),
perfetto::Category("gpu").SetDescription("Events from the emulated GPU"), perfetto::Category("gpu").SetDescription("Events from the emulated GPU"),
perfetto::Category("service").SetDescription("Events from the HLE sysmodule implementations"), perfetto::Category("service").SetDescription("Events from the HLE sysmodule implementations"),
perfetto::Category("containers").SetDescription("Events from custom container implementations") perfetto::Category("containers").SetDescription("Events from custom container implementations")

View File

@ -23,6 +23,8 @@ namespace skyline::gpu {
return; return;
std::scoped_lock lock{*buffer}; std::scoped_lock lock{*buffer};
}, [weakThis] { }, [weakThis] {
TRACE_EVENT("gpu", "Buffer::ReadTrap");
auto buffer{weakThis.lock()}; auto buffer{weakThis.lock()};
if (!buffer) if (!buffer)
return true; return true;
@ -34,6 +36,8 @@ namespace skyline::gpu {
return true; return true;
}, [weakThis] { }, [weakThis] {
TRACE_EVENT("gpu", "Buffer::WriteTrap");
auto buffer{weakThis.lock()}; auto buffer{weakThis.lock()};
if (!buffer) if (!buffer)
return true; return true;

View File

@ -152,6 +152,8 @@ namespace skyline::gpu {
std::scoped_lock lock{*texture}; std::scoped_lock lock{*texture};
}, [weakThis] { }, [weakThis] {
TRACE_EVENT("gpu", "Texture::ReadTrap");
auto texture{weakThis.lock()}; auto texture{weakThis.lock()};
if (!texture) if (!texture)
return true; return true;
@ -164,6 +166,8 @@ namespace skyline::gpu {
texture->WaitOnFence(); texture->WaitOnFence();
return true; return true;
}, [weakThis] { }, [weakThis] {
TRACE_EVENT("gpu", "Texture::WriteTrap");
auto texture{weakThis.lock()}; auto texture{weakThis.lock()};
if (!texture) if (!texture)
return true; return true;

View File

@ -409,6 +409,8 @@ namespace skyline::nce {
NCE::CallbackEntry::CallbackEntry(TrapProtection protection, LockCallback lockCallback, TrapCallback readCallback, TrapCallback writeCallback) : protection{protection}, lockCallback{std::move(lockCallback)}, readCallback{std::move(readCallback)}, writeCallback{std::move(writeCallback)} {} NCE::CallbackEntry::CallbackEntry(TrapProtection protection, LockCallback lockCallback, TrapCallback readCallback, TrapCallback writeCallback) : protection{protection}, lockCallback{std::move(lockCallback)}, readCallback{std::move(readCallback)}, writeCallback{std::move(writeCallback)} {}
void NCE::ReprotectIntervals(const std::vector<TrapMap::Interval> &intervals, TrapProtection protection) { void NCE::ReprotectIntervals(const std::vector<TrapMap::Interval> &intervals, TrapProtection protection) {
TRACE_EVENT("host", "NCE::ReprotectIntervals");
auto reprotectIntervalsWithFunction = [&intervals](auto getProtection) { auto reprotectIntervalsWithFunction = [&intervals](auto getProtection) {
for (auto region : intervals) { for (auto region : intervals) {
region = region.Align(PAGE_SIZE); region = region.Align(PAGE_SIZE);
@ -455,6 +457,7 @@ namespace skyline::nce {
}); });
// Page out regions that are no longer accessible, these should be paged back in by a callback // Page out regions that are no longer accessible, these should be paged back in by a callback
TRACE_EVENT("host", "NCE::ReprotectIntervals::PageOut");
for (auto region : intervals) { for (auto region : intervals) {
auto freeStart{util::AlignUp(region.start, PAGE_SIZE)}, freeEnd{util::AlignDown(region.end, PAGE_SIZE)}; // We want to avoid the first and last page as they may contain data that won't be paged back in by the callback auto freeStart{util::AlignUp(region.start, PAGE_SIZE)}, freeEnd{util::AlignDown(region.end, PAGE_SIZE)}; // We want to avoid the first and last page as they may contain data that won't be paged back in by the callback
ssize_t freeSize{freeEnd - freeStart}; ssize_t freeSize{freeEnd - freeStart};
@ -467,6 +470,8 @@ namespace skyline::nce {
} }
bool NCE::TrapHandler(u8 *address, bool write) { bool NCE::TrapHandler(u8 *address, bool write) {
TRACE_EVENT("host", "NCE::TrapHandler");
LockCallback lockCallback{}; LockCallback lockCallback{};
while (true) { while (true) {
if (lockCallback) { if (lockCallback) {
@ -531,6 +536,7 @@ namespace skyline::nce {
constexpr NCE::TrapHandle::TrapHandle(const TrapMap::GroupHandle &handle) : TrapMap::GroupHandle(handle) {} constexpr NCE::TrapHandle::TrapHandle(const TrapMap::GroupHandle &handle) : TrapMap::GroupHandle(handle) {}
NCE::TrapHandle NCE::TrapRegions(span<span<u8>> regions, bool writeOnly, const LockCallback &lockCallback, const TrapCallback &readCallback, const TrapCallback &writeCallback) { NCE::TrapHandle NCE::TrapRegions(span<span<u8>> regions, bool writeOnly, const LockCallback &lockCallback, const TrapCallback &readCallback, const TrapCallback &writeCallback) {
TRACE_EVENT("host", "NCE::TrapRegions");
std::scoped_lock lock(trapMutex); std::scoped_lock lock(trapMutex);
auto protection{writeOnly ? TrapProtection::WriteOnly : TrapProtection::ReadWrite}; auto protection{writeOnly ? TrapProtection::WriteOnly : TrapProtection::ReadWrite};
TrapHandle handle{trapMap.Insert(regions, CallbackEntry{protection, lockCallback, readCallback, writeCallback})}; TrapHandle handle{trapMap.Insert(regions, CallbackEntry{protection, lockCallback, readCallback, writeCallback})};
@ -539,6 +545,7 @@ namespace skyline::nce {
} }
void NCE::RetrapRegions(TrapHandle handle, bool writeOnly) { void NCE::RetrapRegions(TrapHandle handle, bool writeOnly) {
TRACE_EVENT("host", "NCE::RetrapRegions");
std::scoped_lock lock(trapMutex); std::scoped_lock lock(trapMutex);
auto protection{writeOnly ? TrapProtection::WriteOnly : TrapProtection::ReadWrite}; auto protection{writeOnly ? TrapProtection::WriteOnly : TrapProtection::ReadWrite};
handle->value.protection = protection; handle->value.protection = protection;
@ -546,12 +553,14 @@ namespace skyline::nce {
} }
void NCE::RemoveTrap(TrapHandle handle) { void NCE::RemoveTrap(TrapHandle handle) {
TRACE_EVENT("host", "NCE::RemoveTrap");
std::scoped_lock lock(trapMutex); std::scoped_lock lock(trapMutex);
handle->value.protection = TrapProtection::None; handle->value.protection = TrapProtection::None;
ReprotectIntervals(handle->intervals, TrapProtection::None); ReprotectIntervals(handle->intervals, TrapProtection::None);
} }
void NCE::DeleteTrap(TrapHandle handle) { void NCE::DeleteTrap(TrapHandle handle) {
TRACE_EVENT("host", "NCE::DeleteTrap");
std::scoped_lock lock(trapMutex); std::scoped_lock lock(trapMutex);
handle->value.protection = TrapProtection::None; handle->value.protection = TrapProtection::None;
ReprotectIntervals(handle->intervals, TrapProtection::None); ReprotectIntervals(handle->intervals, TrapProtection::None);