summaryrefslogtreecommitdiff
path: root/src/common/heap_tracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/heap_tracker.cpp')
-rw-r--r--src/common/heap_tracker.cpp36
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
12namespace { 12namespace {
13 13
14constexpr s64 MaxResidentMapCount = 0x8000; 14s64 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
18HeapTracker::HeapTracker(Common::HostMemory& buffer) : m_buffer(buffer) {} 31HeapTracker::HeapTracker(Common::HostMemory& buffer)
32 : m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}
19HeapTracker::~HeapTracker() = default; 33HeapTracker::~HeapTracker() = default;
20 34
21void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, 35void 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