summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar kkoniuszy2023-06-01 17:21:22 +0200
committerGravatar kkoniuszy2023-06-01 22:57:27 +0200
commit584e8b5c52db95a92f818a0fc1b2a64f8a42e524 (patch)
tree19ef36314f2f334a8ef93a6f76e002bcc09f678a /src
parentMerge pull request #10541 from zhaobot/tx-update-20230601030142 (diff)
downloadyuzu-584e8b5c52db95a92f818a0fc1b2a64f8a42e524.tar.gz
yuzu-584e8b5c52db95a92f818a0fc1b2a64f8a42e524.tar.xz
yuzu-584e8b5c52db95a92f818a0fc1b2a64f8a42e524.zip
host_memory: merge adjacent placeholder mappings on Linux
Track the private anonymous placeholder mappings created by Unmap() and wherever possible, replace existing placeholders with larger ones instead of creating many small ones. This helps with the buildup of mappings in /proc/YUZU_PID/maps after a longer gaming session, improving stability without having to increase vm.max_map_count to a ridiculous value. The amount of placeholder mappings will no longer outgrow the amount of actual memfd mappings in cases of high memory fragmentation.
Diffstat (limited to 'src')
-rw-r--r--src/common/host_memory.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 8e4f1f97a..01457d8c6 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -14,6 +14,7 @@
14#ifndef _GNU_SOURCE 14#ifndef _GNU_SOURCE
15#define _GNU_SOURCE 15#define _GNU_SOURCE
16#endif 16#endif
17#include <boost/icl/interval_set.hpp>
17#include <fcntl.h> 18#include <fcntl.h>
18#include <sys/mman.h> 19#include <sys/mman.h>
19#include <unistd.h> 20#include <unistd.h>
@@ -415,6 +416,7 @@ public:
415 madvise(virtual_base, virtual_size, MADV_HUGEPAGE); 416 madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
416#endif 417#endif
417 418
419 placeholders.add({0, virtual_size});
418 good = true; 420 good = true;
419 } 421 }
420 422
@@ -423,6 +425,10 @@ public:
423 } 425 }
424 426
425 void Map(size_t virtual_offset, size_t host_offset, size_t length) { 427 void Map(size_t virtual_offset, size_t host_offset, size_t length) {
428 {
429 std::scoped_lock lock{placeholder_mutex};
430 placeholders.subtract({virtual_offset, virtual_offset + length});
431 }
426 432
427 void* ret = mmap(virtual_base + virtual_offset, length, PROT_READ | PROT_WRITE, 433 void* ret = mmap(virtual_base + virtual_offset, length, PROT_READ | PROT_WRITE,
428 MAP_SHARED | MAP_FIXED, fd, host_offset); 434 MAP_SHARED | MAP_FIXED, fd, host_offset);
@@ -433,6 +439,19 @@ public:
433 // The method name is wrong. We're still talking about the virtual range. 439 // The method name is wrong. We're still talking about the virtual range.
434 // We don't want to unmap, we want to reserve this memory. 440 // We don't want to unmap, we want to reserve this memory.
435 441
442 {
443 std::scoped_lock lock{placeholder_mutex};
444 auto it = placeholders.find({virtual_offset - 1, virtual_offset + length + 1});
445
446 if (it != placeholders.end()) {
447 size_t prev_upper = virtual_offset + length;
448 virtual_offset = std::min(virtual_offset, it->lower());
449 length = std::max(it->upper(), prev_upper) - virtual_offset;
450 }
451
452 placeholders.add({virtual_offset, virtual_offset + length});
453 }
454
436 void* ret = mmap(virtual_base + virtual_offset, length, PROT_NONE, 455 void* ret = mmap(virtual_base + virtual_offset, length, PROT_NONE,
437 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 456 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
438 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); 457 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
@@ -476,6 +495,9 @@ private:
476 } 495 }
477 496
478 int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create 497 int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create
498
499 boost::icl::interval_set<size_t> placeholders; ///< Mapped placeholders
500 std::mutex placeholder_mutex; ///< Mutex for placeholders
479}; 501};
480 502
481#else // ^^^ Linux ^^^ vvv Generic vvv 503#else // ^^^ Linux ^^^ vvv Generic vvv