diff options
Diffstat (limited to 'src/common/heap_tracker.cpp')
| -rw-r--r-- | src/common/heap_tracker.cpp | 36 |
1 files changed, 27 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <fstream> |
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | 6 | ||
| 7 | #include "common/heap_tracker.h" | 7 | #include "common/heap_tracker.h" |
| @@ -11,11 +11,25 @@ namespace Common { | |||
| 11 | 11 | ||
| 12 | namespace { | 12 | namespace { |
| 13 | 13 | ||
| 14 | constexpr s64 MaxResidentMapCount = 0x8000; | 14 | s64 GetMaxPermissibleResidentMapCount() { |
| 15 | // Default value. | ||
| 16 | s64 value = 65530; | ||
| 17 | |||
| 18 | // Try to read how many mappings we can make. | ||
| 19 | std::ifstream s("/proc/sys/vm/max_map_count"); | ||
| 20 | s >> value; | ||
| 21 | |||
| 22 | // Print, for debug. | ||
| 23 | LOG_INFO(HW_Memory, "Current maximum map count: {}", value); | ||
| 24 | |||
| 25 | // Allow 20000 maps for other code and to account for split inaccuracy. | ||
| 26 | return std::max<s64>(value - 20000, 0); | ||
| 27 | } | ||
| 15 | 28 | ||
| 16 | } // namespace | 29 | } // namespace |
| 17 | 30 | ||
| 18 | HeapTracker::HeapTracker(Common::HostMemory& buffer) : m_buffer(buffer) {} | 31 | HeapTracker::HeapTracker(Common::HostMemory& buffer) |
| 32 | : m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {} | ||
| 19 | HeapTracker::~HeapTracker() = default; | 33 | HeapTracker::~HeapTracker() = default; |
| 20 | 34 | ||
| 21 | void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, | 35 | 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 | |||
| 74 | } | 88 | } |
| 75 | 89 | ||
| 76 | // Erase from map. | 90 | // Erase from map. |
| 77 | it = m_mappings.erase(it); | ||
| 78 | ASSERT(--m_map_count >= 0); | 91 | ASSERT(--m_map_count >= 0); |
| 92 | it = m_mappings.erase(it); | ||
| 79 | 93 | ||
| 80 | // Free the item. | 94 | // Free the item. |
| 81 | delete item; | 95 | delete item; |
| @@ -94,8 +108,8 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p | |||
| 94 | this->SplitHeapMap(virtual_offset, size); | 108 | this->SplitHeapMap(virtual_offset, size); |
| 95 | 109 | ||
| 96 | // Declare tracking variables. | 110 | // Declare tracking variables. |
| 111 | const VAddr end = virtual_offset + size; | ||
| 97 | VAddr cur = virtual_offset; | 112 | VAddr cur = virtual_offset; |
| 98 | VAddr end = virtual_offset + size; | ||
| 99 | 113 | ||
| 100 | while (cur < end) { | 114 | while (cur < end) { |
| 101 | VAddr next = cur; | 115 | VAddr next = cur; |
| @@ -167,7 +181,7 @@ bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) { | |||
| 167 | it->tick = m_tick++; | 181 | it->tick = m_tick++; |
| 168 | 182 | ||
| 169 | // Check if we need to rebuild. | 183 | // Check if we need to rebuild. |
| 170 | if (m_resident_map_count > MaxResidentMapCount) { | 184 | if (m_resident_map_count > m_max_resident_map_count) { |
| 171 | rebuild_required = true; | 185 | rebuild_required = true; |
| 172 | } | 186 | } |
| 173 | 187 | ||
| @@ -193,8 +207,12 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() { | |||
| 193 | 207 | ||
| 194 | ASSERT(!m_resident_mappings.empty()); | 208 | ASSERT(!m_resident_mappings.empty()); |
| 195 | 209 | ||
| 196 | // Unmap so we have at least 4 maps available. | 210 | // Dump half of the mappings. |
| 197 | const size_t desired_count = std::min(m_resident_map_count, MaxResidentMapCount - 4); | 211 | // |
| 212 | // Despite being worse in theory, this has proven to be better in practice than more | ||
| 213 | // regularly dumping a smaller amount, because it significantly reduces average case | ||
| 214 | // lock contention. | ||
| 215 | const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; | ||
| 198 | const size_t evict_count = m_resident_map_count - desired_count; | 216 | const size_t evict_count = m_resident_map_count - desired_count; |
| 199 | auto it = m_resident_mappings.begin(); | 217 | auto it = m_resident_mappings.begin(); |
| 200 | 218 | ||
| @@ -247,8 +265,8 @@ void HeapTracker::SplitHeapMapLocked(VAddr offset) { | |||
| 247 | 265 | ||
| 248 | // If resident, also insert into resident map. | 266 | // If resident, also insert into resident map. |
| 249 | if (right->is_resident) { | 267 | if (right->is_resident) { |
| 250 | m_resident_mappings.insert(*right); | ||
| 251 | m_resident_map_count++; | 268 | m_resident_map_count++; |
| 269 | m_resident_mappings.insert(*right); | ||
| 252 | } | 270 | } |
| 253 | } | 271 | } |
| 254 | 272 | ||