From patchwork Thu Mar 5 20:38:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 2971 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BB0F360427 for ; Thu, 5 Mar 2020 21:38:24 +0100 (CET) X-Halon-ID: 420dd68b-5f21-11ea-9f85-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p4fca2392.dip0.t-ipconnect.de [79.202.35.146]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 420dd68b-5f21-11ea-9f85-005056917a89; Thu, 05 Mar 2020 21:38:23 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Thu, 5 Mar 2020 21:38:08 +0100 Message-Id: <20200305203808.536050-8-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200305203808.536050-1-niklas.soderlund@ragnatech.se> References: <20200305203808.536050-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 7/7] libcamera: V4L2BufferCache: Improve cache eviction strategy X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Mar 2020 20:38:25 -0000 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 --- * Changes since v3 - Group C++ header includes. - s/UINT32_MAX/UINT64_MAX/ - Use std::memory_order_acq_rel instead of std::memory_order_seq_cst order to fetch_add() of the atomic sequence number. * Changes since v2 - Use a sequence number instead of timestamp to judge age of a cached entry. --- src/libcamera/include/v4l2_videodevice.h | 7 +++++-- src/libcamera/v4l2_videodevice.cpp | 23 +++++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h index 359b366454e4e782..04802012d5315d67 100644 --- a/src/libcamera/include/v4l2_videodevice.h +++ b/src/libcamera/include/v4l2_videodevice.h @@ -7,11 +7,12 @@ #ifndef __LIBCAMERA_V4L2_VIDEODEVICE_H__ #define __LIBCAMERA_V4L2_VIDEODEVICE_H__ +#include +#include #include #include #include -#include #include #include @@ -120,11 +121,12 @@ private: { public: Entry(); - Entry(bool free, const FrameBuffer &buffer); + Entry(bool free, uint64_t lastUsed, const FrameBuffer &buffer); bool operator==(const FrameBuffer &buffer) const; bool free; + uint64_t lastUsed; private: struct Plane { @@ -140,6 +142,7 @@ private: std::vector planes_; }; + std::atomic_uint64_t lastUsedCounter_; std::vector cache_; /* \todo Expose the miss counter through an instrumentation API. */ unsigned int missCounter_; diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index c495de85f26efe14..ca0d147f5fc1ea58 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);