From a3b37c041aef75e14621a244b88c88f03d1eba66 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 7 Mar 2026 12:31:59 +0100 Subject: [PATCH] Core: Optimize RemoveHostPageTableMappings This switches from an O(log(N) * M) algorithm to an O(N * log(M)) algorithm. This is advantageous because N, the size of `mappings`, is usually much smaller than M, the size of `m_page_table_mapped_entries`. RemoveLargePageTableMapping already did something similar, so we can even deduplicate some code between it and RemoveHostPageTableMappings. Speeds up Rogue Squadron 3 by roughly 3% on my PC. --- Source/Core/Core/HW/Memmap.cpp | 32 ++++++++++++-------------------- Source/Core/Core/HW/Memmap.h | 2 +- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index c7ec1debb0..122f524555 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -438,7 +438,9 @@ void MemoryManager::RemovePageTableMappings(const std::set& mappings) switch (m_host_page_type) { case HostPageType::SmallPages: - return RemoveHostPageTableMappings(mappings); + for (u32 logical_address : mappings) + RemoveHostPageTableMapping(logical_address); + return; case HostPageType::LargePages: for (u32 logical_address : mappings) RemoveLargePageTableMapping(logical_address); @@ -453,15 +455,7 @@ void MemoryManager::RemoveLargePageTableMapping(u32 logical_address) RemoveLargePageTableMapping(logical_address, m_large_readable_pages); RemoveLargePageTableMapping(logical_address, m_large_writeable_pages); - const u32 aligned_logical_address = logical_address & ~(m_page_size - 1); - const auto it = m_page_table_mapped_entries.find(aligned_logical_address); - if (it != m_page_table_mapped_entries.end()) - { - const LogicalMemoryView& entry = it->second; - m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); - - m_page_table_mapped_entries.erase(it); - } + RemoveHostPageTableMapping(logical_address & ~(m_page_size - 1)); } void MemoryManager::RemoveLargePageTableMapping(u32 logical_address, @@ -472,18 +466,16 @@ void MemoryManager::RemoveLargePageTableMapping(u32 logical_address, it->second[(logical_address & (m_page_size - 1)) / PowerPC::HW_PAGE_SIZE] = INVALID_MAPPING; } -void MemoryManager::RemoveHostPageTableMappings(const std::set& mappings) +void MemoryManager::RemoveHostPageTableMapping(u32 logical_address) { - if (mappings.empty()) - return; + const auto it = m_page_table_mapped_entries.find(logical_address); + if (it != m_page_table_mapped_entries.end()) + { + const LogicalMemoryView& entry = it->second; + m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); - std::erase_if(m_page_table_mapped_entries, [this, &mappings](const auto& pair) { - const auto& [logical_address, entry] = pair; - const bool remove = mappings.contains(logical_address); - if (remove) - m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size); - return remove; - }); + m_page_table_mapped_entries.erase(it); + } } void MemoryManager::RemoveAllPageTableMappings() diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index 4b33776a62..421fc32e0b 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -294,6 +294,6 @@ private: u32 logical_size); void RemoveLargePageTableMapping(u32 logical_address); void RemoveLargePageTableMapping(u32 logical_address, std::map>& map); - void RemoveHostPageTableMappings(const std::set& mappings); + void RemoveHostPageTableMapping(u32 logical_address); }; } // namespace Memory