From 4e0d1eca10b7d2cf0ccbdbebee698d6b716d075b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 16 Feb 2020 16:51:53 +0100 Subject: libcamera: V4L2BufferCache: Improve cache eviction strategy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The strategy used to find a free cache entry in the first implementation was not the smartest, it picked the first free entry. This lead to unwanted performance issues as the cache was not used as good as it could for imported buffers. Improve this by adding a last usage sequence number to the cache entries and change the eviction strategy to use the oldest free entry instead of the first one it finds. Signed-off-by: Niklas Söderlund Reviewed-by: Naushir Patuck Reviewed-by: Laurent Pinchart --- src/libcamera/v4l2_videodevice.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/libcamera/v4l2_videodevice.cpp') diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index c495de85..ca0d147f 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -162,7 +162,7 @@ LOG_DECLARE_CATEGORY(V4L2) * buffer import, with buffers added to the cache as they are queued. */ V4L2BufferCache::V4L2BufferCache(unsigned int numEntries) - : missCounter_(0) + : lastUsedCounter_(1), missCounter_(0) { cache_.resize(numEntries); } @@ -176,10 +176,12 @@ V4L2BufferCache::V4L2BufferCache(unsigned int numEntries) * allocated. */ V4L2BufferCache::V4L2BufferCache(const std::vector> &buffers) - : missCounter_(0) + : lastUsedCounter_(1), missCounter_(0) { for (const std::unique_ptr &buffer : buffers) - cache_.emplace_back(true, buffer->planes()); + cache_.emplace_back(true, + lastUsedCounter_.fetch_add(1, std::memory_order_acq_rel), + buffer->planes()); } V4L2BufferCache::~V4L2BufferCache() @@ -205,6 +207,7 @@ int V4L2BufferCache::get(const FrameBuffer &buffer) { bool hit = false; int use = -1; + uint64_t oldest = UINT64_MAX; for (unsigned int index = 0; index < cache_.size(); index++) { const Entry &entry = cache_[index]; @@ -219,8 +222,10 @@ int V4L2BufferCache::get(const FrameBuffer &buffer) break; } - if (use < 0) + if (entry.lastUsed < oldest) { use = index; + oldest = entry.lastUsed; + } } if (!hit) @@ -229,7 +234,9 @@ int V4L2BufferCache::get(const FrameBuffer &buffer) if (use < 0) return -ENOENT; - cache_[use] = Entry(false, buffer); + cache_[use] = Entry(false, + lastUsedCounter_.fetch_add(1, std::memory_order_acq_rel), + buffer); return use; } @@ -245,12 +252,12 @@ void V4L2BufferCache::put(unsigned int index) } V4L2BufferCache::Entry::Entry() - : free(true) + : free(true), lastUsed(0) { } -V4L2BufferCache::Entry::Entry(bool free, const FrameBuffer &buffer) - : free(free) +V4L2BufferCache::Entry::Entry(bool free, uint64_t lastUsed, const FrameBuffer &buffer) + : free(free), lastUsed(lastUsed) { for (const FrameBuffer::Plane &plane : buffer.planes()) planes_.emplace_back(plane); -- cgit v1.2.1