From 19d4f28001d3a8e28b41187a7940d14d0a8d708c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 20 May 2020 23:55:40 -0300 Subject: buffer_cache: Use boost::container::small_vector for maps in range Most overlaps in the buffer cache only contain one mapped address. We can avoid close to all heap allocations once the buffer cache is warmed up by using a small_vector with a stack size of one. --- src/video_core/buffer_cache/buffer_cache.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index fb12af9d8..0c8500c04 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,10 @@ namespace VideoCommon { template class BufferCache { + using IntervalSet = boost::icl::interval_set; + using IntervalType = typename IntervalSet::interval_type; + using VectorMapInterval = boost::container::small_vector; + public: using BufferInfo = std::pair; @@ -133,7 +138,7 @@ public: void FlushRegion(VAddr addr, std::size_t size) { std::lock_guard lock{mutex}; - std::vector objects = GetMapsInRange(addr, size); + VectorMapInterval objects = GetMapsInRange(addr, size); std::sort(objects.begin(), objects.end(), [](MapInterval* lhs, MapInterval* rhs) { return lhs->ticks < rhs->ticks; }); for (MapInterval* object : objects) { @@ -148,7 +153,7 @@ public: bool MustFlushRegion(VAddr addr, std::size_t size) { std::lock_guard lock{mutex}; - const std::vector objects = GetMapsInRange(addr, size); + const VectorMapInterval objects = GetMapsInRange(addr, size); return std::any_of(objects.cbegin(), objects.cend(), [](const MapInterval* map) { return map->is_modified && map->is_registered; }); @@ -158,8 +163,7 @@ public: void InvalidateRegion(VAddr addr, u64 size) { std::lock_guard lock{mutex}; - std::vector objects = GetMapsInRange(addr, size); - for (auto& object : objects) { + for (auto& object : GetMapsInRange(addr, size)) { if (object->is_registered) { Unregister(object); } @@ -314,7 +318,7 @@ protected: private: MapInterval* MapAddress(const OwnerBuffer& block, GPUVAddr gpu_addr, VAddr cpu_addr, std::size_t size) { - std::vector overlaps = GetMapsInRange(cpu_addr, size); + const VectorMapInterval overlaps = GetMapsInRange(cpu_addr, size); if (overlaps.empty()) { auto& memory_manager = system.GPU().MemoryManager(); const VAddr cpu_addr_end = cpu_addr + size; @@ -368,7 +372,7 @@ private: } void UpdateBlock(const OwnerBuffer& block, VAddr start, VAddr end, - std::vector& overlaps) { + const VectorMapInterval& overlaps) { const IntervalType base_interval{start, end}; IntervalSet interval_set{}; interval_set.add(base_interval); @@ -387,14 +391,13 @@ private: } } - std::vector GetMapsInRange(VAddr addr, std::size_t size) { + VectorMapInterval GetMapsInRange(VAddr addr, std::size_t size) { + VectorMapInterval result; if (size == 0) { - return {}; + return result; } - std::vector result; const VAddr addr_end = addr + size; - auto it = mapped_addresses.lower_bound(addr); if (it != mapped_addresses.begin()) { --it; @@ -574,10 +577,9 @@ private: u64 buffer_offset = 0; u64 buffer_offset_base = 0; - using IntervalSet = boost::icl::interval_set; - using IntervalType = typename IntervalSet::interval_type; std::list mapped_addresses_storage; // Temporary hack - boost::intrusive::set> mapped_addresses; + boost::intrusive::set> + mapped_addresses; static constexpr u64 write_page_bit = 11; std::unordered_map written_pages; -- cgit v1.2.3