diff options
| -rw-r--r-- | src/common/heap_tracker.cpp | 36 | ||||
| -rw-r--r-- | src/common/heap_tracker.h | 1 | 
2 files changed, 28 insertions, 9 deletions
| diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index 95dc8aa1e..683208795 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -1,7 +1,7 @@  // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later -#include <algorithm> +#include <fstream>  #include <vector>  #include "common/heap_tracker.h" @@ -11,11 +11,25 @@ namespace Common {  namespace { -constexpr s64 MaxResidentMapCount = 0x8000; +s64 GetMaxPermissibleResidentMapCount() { +    // Default value. +    s64 value = 65530; + +    // Try to read how many mappings we can make. +    std::ifstream s("/proc/sys/vm/max_map_count"); +    s >> value; + +    // Print, for debug. +    LOG_INFO(HW_Memory, "Current maximum map count: {}", value); + +    // Allow 20000 maps for other code and to account for split inaccuracy. +    return std::max<s64>(value - 20000, 0); +}  } // namespace -HeapTracker::HeapTracker(Common::HostMemory& buffer) : m_buffer(buffer) {} +HeapTracker::HeapTracker(Common::HostMemory& buffer) +    : m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}  HeapTracker::~HeapTracker() = default;  void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, @@ -74,8 +88,8 @@ void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_hea              }              // Erase from map. -            it = m_mappings.erase(it);              ASSERT(--m_map_count >= 0); +            it = m_mappings.erase(it);              // Free the item.              delete item; @@ -94,8 +108,8 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p      this->SplitHeapMap(virtual_offset, size);      // Declare tracking variables. +    const VAddr end = virtual_offset + size;      VAddr cur = virtual_offset; -    VAddr end = virtual_offset + size;      while (cur < end) {          VAddr next = cur; @@ -167,7 +181,7 @@ bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) {          it->tick = m_tick++;          // Check if we need to rebuild. -        if (m_resident_map_count > MaxResidentMapCount) { +        if (m_resident_map_count > m_max_resident_map_count) {              rebuild_required = true;          } @@ -193,8 +207,12 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {      ASSERT(!m_resident_mappings.empty()); -    // Unmap so we have at least 4 maps available. -    const size_t desired_count = std::min(m_resident_map_count, MaxResidentMapCount - 4); +    // Dump half of the mappings. +    // +    // Despite being worse in theory, this has proven to be better in practice than more +    // regularly dumping a smaller amount, because it significantly reduces average case +    // lock contention. +    const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2;      const size_t evict_count = m_resident_map_count - desired_count;      auto it = m_resident_mappings.begin(); @@ -247,8 +265,8 @@ void HeapTracker::SplitHeapMapLocked(VAddr offset) {      // If resident, also insert into resident map.      if (right->is_resident) { -        m_resident_mappings.insert(*right);          m_resident_map_count++; +        m_resident_mappings.insert(*right);      }  } diff --git a/src/common/heap_tracker.h b/src/common/heap_tracker.h index cc16041d9..ee5b0bf43 100644 --- a/src/common/heap_tracker.h +++ b/src/common/heap_tracker.h @@ -86,6 +86,7 @@ private:  private:      Common::HostMemory& m_buffer; +    const s64 m_max_resident_map_count;      std::shared_mutex m_rebuild_lock{};      std::mutex m_lock{}; | 
