{"id":2963,"url":"https://patchwork.libcamera.org/api/1.1/patches/2963/?format=json","web_url":"https://patchwork.libcamera.org/patch/2963/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20200304232246.325384-8-niklas.soderlund@ragnatech.se>","date":"2020-03-04T23:22:46","name":"[libcamera-devel,v3,7/7] libcamera: V4L2BufferCache: Improve cache eviction strategy","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"a642c0df15ef1fa911ff5ac462d268fa9a92c135","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/1.1/people/5/?format=json","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/2963/mbox/","series":[{"id":701,"url":"https://patchwork.libcamera.org/api/1.1/series/701/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=701","date":"2020-03-04T23:22:39","name":"libcamera: V4L2BufferCache: Improve cache","version":3,"mbox":"https://patchwork.libcamera.org/series/701/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/2963/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/2963/checks/","tags":{},"headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net\n\t[195.74.38.227])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 77CC96285C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Mar 2020 00:23:49 +0100 (CET)","from bismarck.berto.se (p4fca2392.dip0.t-ipconnect.de\n\t[79.202.35.146]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA\n\tid 334a5e81-5e6f-11ea-9f85-005056917a89;\n\tThu, 05 Mar 2020 00:23:48 +0100 (CET)"],"X-Halon-ID":"334a5e81-5e6f-11ea-9f85-005056917a89","Authorized-sender":"niklas@soderlund.pp.se","From":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","To":"libcamera-devel@lists.libcamera.org","Date":"Thu,  5 Mar 2020 00:22:46 +0100","Message-Id":"<20200304232246.325384-8-niklas.soderlund@ragnatech.se>","X-Mailer":"git-send-email 2.25.1","In-Reply-To":"<20200304232246.325384-1-niklas.soderlund@ragnatech.se>","References":"<20200304232246.325384-1-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v3 7/7] libcamera: V4L2BufferCache:\n\tImprove cache eviction strategy","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Wed, 04 Mar 2020 23:23:49 -0000"},"content":"The strategy used to find a free cache entry in the first implementation\nwas not the smartest, it picked the first free entry. This lead to\nunwanted performance issues as the cache was not used as good as it\ncould for imported buffers.\n\nImprove this by adding a last usage sequence numer to the cache entries\nand change the eviction strategy to use the oldest free entry instead of\nthe first one it finds.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\nReviewed-by: Naushir Patuck <naush@raspberrypi.com>\n---\n* Changes since v2\n- Use a sequence number instead of timestamp to judge age of a cached\n  entry.\n---\n src/libcamera/include/v4l2_videodevice.h |  5 ++++-\n src/libcamera/v4l2_videodevice.cpp       | 20 ++++++++++++--------\n 2 files changed, 16 insertions(+), 9 deletions(-)","diff":"diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h\nindex 359b366454e4e782..993ebb3069c595bf 100644\n--- a/src/libcamera/include/v4l2_videodevice.h\n+++ b/src/libcamera/include/v4l2_videodevice.h\n@@ -10,6 +10,7 @@\n #include <string>\n #include <vector>\n \n+#include <atomic>\n #include <linux/videodev2.h>\n #include <memory>\n \n@@ -120,11 +121,12 @@ private:\n \t{\n \tpublic:\n \t\tEntry();\n-\t\tEntry(bool free, const FrameBuffer &buffer);\n+\t\tEntry(bool free, uint64_t lastUsed, const FrameBuffer &buffer);\n \n \t\tbool operator==(const FrameBuffer &buffer) const;\n \n \t\tbool free;\n+\t\tuint64_t lastUsed;\n \n \tprivate:\n \t\tstruct Plane {\n@@ -140,6 +142,7 @@ private:\n \t\tstd::vector<Plane> planes_;\n \t};\n \n+\tstd::atomic_uint64_t lastUsedCounter_;\n \tstd::vector<Entry> cache_;\n \t/* \\todo Expose the miss counter through an instrumentation API. */\n \tunsigned int missCounter_;\ndiff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\nindex c495de85f26efe14..3043aebfe0588290 100644\n--- a/src/libcamera/v4l2_videodevice.cpp\n+++ b/src/libcamera/v4l2_videodevice.cpp\n@@ -162,7 +162,7 @@ LOG_DECLARE_CATEGORY(V4L2)\n  * buffer import, with buffers added to the cache as they are queued.\n  */\n V4L2BufferCache::V4L2BufferCache(unsigned int numEntries)\n-\t: missCounter_(0)\n+\t: lastUsedCounter_(1), missCounter_(0)\n {\n \tcache_.resize(numEntries);\n }\n@@ -176,10 +176,11 @@ V4L2BufferCache::V4L2BufferCache(unsigned int numEntries)\n  * allocated.\n  */\n V4L2BufferCache::V4L2BufferCache(const std::vector<std::unique_ptr<FrameBuffer>> &buffers)\n-\t: missCounter_(0)\n+\t: lastUsedCounter_(1), missCounter_(0)\n {\n \tfor (const std::unique_ptr<FrameBuffer> &buffer : buffers)\n-\t\tcache_.emplace_back(true, buffer->planes());\n+\t\tcache_.emplace_back(true, lastUsedCounter_.fetch_add(1),\n+\t\t\t\t    buffer->planes());\n }\n \n V4L2BufferCache::~V4L2BufferCache()\n@@ -205,6 +206,7 @@ int V4L2BufferCache::get(const FrameBuffer &buffer)\n {\n \tbool hit = false;\n \tint use = -1;\n+\tuint64_t oldest = UINT32_MAX;\n \n \tfor (unsigned int index = 0; index < cache_.size(); index++) {\n \t\tconst Entry &entry = cache_[index];\n@@ -219,8 +221,10 @@ int V4L2BufferCache::get(const FrameBuffer &buffer)\n \t\t\tbreak;\n \t\t}\n \n-\t\tif (use < 0)\n+\t\tif (entry.lastUsed < oldest) {\n \t\t\tuse = index;\n+\t\t\toldest = entry.lastUsed;\n+\t\t}\n \t}\n \n \tif (!hit)\n@@ -229,7 +233,7 @@ int V4L2BufferCache::get(const FrameBuffer &buffer)\n \tif (use < 0)\n \t\treturn -ENOENT;\n \n-\tcache_[use] = Entry(false, buffer);\n+\tcache_[use] = Entry(false, lastUsedCounter_.fetch_add(1), buffer);\n \n \treturn use;\n }\n@@ -245,12 +249,12 @@ void V4L2BufferCache::put(unsigned int index)\n }\n \n V4L2BufferCache::Entry::Entry()\n-\t: free(true)\n+\t: free(true), lastUsed(0)\n {\n }\n \n-V4L2BufferCache::Entry::Entry(bool free, const FrameBuffer &buffer)\n-\t: free(free)\n+V4L2BufferCache::Entry::Entry(bool free, uint64_t lastUsed, const FrameBuffer &buffer)\n+\t: free(free), lastUsed(lastUsed)\n {\n \tfor (const FrameBuffer::Plane &plane : buffer.planes())\n \t\tplanes_.emplace_back(plane);\n","prefixes":["libcamera-devel","v3","7/7"]}