mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-21 18:58:57 +02:00
[buffer_cache] Add batching support for memory tracker updates (#3288)
I added a batching/ coalescing of ranges in WordManager to reduce calls per pages in UpdatePagesCachedCount, also a test to verify if FlushCachedWrites coalesced (reduces callings to UpdatePagesCachedCount) callings and register each of them to inspect them. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3288 Reviewed-by: Maufeat <sahyno1996@gmail.com> Reviewed-by: DraVee <dravee@eden-emu.dev> Co-authored-by: CamilleLaVey <camillelavey99@gmail.com> Co-committed-by: CamilleLaVey <camillelavey99@gmail.com>
This commit is contained in:
parent
51cc1bc6be
commit
1a9b4b37e1
4 changed files with 155 additions and 6 deletions
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -9,6 +12,7 @@
|
|||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/range_mutex.h"
|
||||
|
|
@ -44,6 +48,7 @@ public:
|
|||
~DeviceMemoryManager();
|
||||
|
||||
static constexpr bool HAS_FLUSH_INVALIDATION = true;
|
||||
static constexpr size_t AS_BITS = Traits::device_virtual_bits;
|
||||
|
||||
void BindInterface(DeviceInterface* device_inter);
|
||||
|
||||
|
|
@ -117,7 +122,12 @@ public:
|
|||
|
||||
void UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta);
|
||||
|
||||
static constexpr size_t AS_BITS = Traits::device_virtual_bits;
|
||||
// New batch API to update multiple ranges with a single lock acquisition.
|
||||
void UpdatePagesCachedBatch(const std::vector<std::pair<DAddr, size_t>>& ranges, s32 delta);
|
||||
|
||||
private:
|
||||
// Internal helper that performs the update assuming the caller already holds the necessary lock.
|
||||
void UpdatePagesCachedCountNoLock(DAddr addr, size_t size, s32 delta);
|
||||
|
||||
private:
|
||||
static constexpr size_t device_virtual_bits = Traits::device_virtual_bits;
|
||||
|
|
@ -214,6 +224,8 @@ private:
|
|||
std::unique_ptr<CachedPages> cached_pages;
|
||||
Common::RangeMutex counter_guard;
|
||||
std::mutex mapping_guard;
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -5,6 +8,8 @@
|
|||
#include <limits>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "common/address_space.h"
|
||||
#include "common/address_space.inc"
|
||||
|
|
@ -507,8 +512,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
|
|||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
|
||||
Common::ScopedRangeLock lk(counter_guard, addr, size);
|
||||
void DeviceMemoryManager<Traits>::UpdatePagesCachedCountNoLock(DAddr addr, size_t size, s32 delta) {
|
||||
u64 uncache_begin = 0;
|
||||
u64 cache_begin = 0;
|
||||
u64 uncache_bytes = 0;
|
||||
|
|
@ -586,4 +590,47 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
|||
release_pending();
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
|
||||
Common::ScopedRangeLock lk(counter_guard, addr, size);
|
||||
UpdatePagesCachedCountNoLock(addr, size, delta);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::UpdatePagesCachedBatch(const std::vector<std::pair<DAddr, size_t>>& ranges, s32 delta) {
|
||||
if (ranges.empty()) {
|
||||
return;
|
||||
}
|
||||
// Make a local copy and sort by address
|
||||
std::vector<std::pair<DAddr, size_t>> tmp = ranges;
|
||||
std::sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
|
||||
// Coalesce adjacent/overlapping ranges
|
||||
std::vector<std::pair<DAddr, size_t>> coalesced;
|
||||
DAddr cur_addr = tmp[0].first;
|
||||
size_t cur_size = tmp[0].second;
|
||||
for (size_t i = 1; i < tmp.size(); ++i) {
|
||||
DAddr next_addr = tmp[i].first;
|
||||
size_t next_size = tmp[i].second;
|
||||
if (cur_addr + cur_size >= next_addr) {
|
||||
// overlapping or contiguous
|
||||
const DAddr end = std::max(cur_addr + cur_size, next_addr + next_size);
|
||||
cur_size = end - cur_addr;
|
||||
} else {
|
||||
coalesced.emplace_back(cur_addr, cur_size);
|
||||
cur_addr = next_addr;
|
||||
cur_size = next_size;
|
||||
}
|
||||
}
|
||||
coalesced.emplace_back(cur_addr, cur_size);
|
||||
|
||||
const DAddr lock_begin = coalesced.front().first;
|
||||
const DAddr lock_end = coalesced.back().first + coalesced.back().second;
|
||||
Common::ScopedRangeLock lk(counter_guard, lock_begin, static_cast<size_t>(lock_end - lock_begin));
|
||||
|
||||
for (const auto& [addr, size] : coalesced) {
|
||||
UpdatePagesCachedCountNoLock(addr, size, delta);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue