[{"id":3935,"web_url":"https://patchwork.libcamera.org/comment/3935/","msgid":"<20200304233821.GF28814@pendragon.ideasonboard.com>","date":"2020-03-04T23:38:21","subject":"Re: [libcamera-devel] [PATCH v3 7/7] libcamera: V4L2BufferCache:\n\tImprove cache eviction strategy","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Thu, Mar 05, 2020 at 12:22:46AM +0100, Niklas Söderlund wrote:\n> The strategy used to find a free cache entry in the first implementation\n> was not the smartest, it picked the first free entry. This lead to\n> unwanted performance issues as the cache was not used as good as it\n> could for imported buffers.\n> \n> Improve this by adding a last usage sequence numer to the cache entries\n\ns/numer/number/\n\n> and change the eviction strategy to use the oldest free entry instead of\n> the first one it finds.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> Reviewed-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(-)\n> \n> diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h\n> index 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\nThis should go with the C++ headers above. So should the memory header.\nYou can fix this \"while at it\", no need for a separate patch ;-)\n\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_;\n> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> index 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\nI think the std::memory_order_acq_rel memory order should be enough for\nthis usage (same below). Should I be mean and ask you to confirm ? :-)\n\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\nUINT64_MAX ?\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\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);","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8682E62734\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Mar 2020 00:38:24 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D858D33E;\n\tThu,  5 Mar 2020 00:38:23 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1583365104;\n\tbh=5iT1gpKJiWU2qLoTk2O1DuuAFfKfv1hJuhSZTa5i/Ww=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=ob7LKTWGwXeLwTTv5tN8cXepHZ5UogZ6XzJbUoJDBEByCL1buEdX+iP1Up17rZp1S\n\t8+L0X4mUn6W8rAcplvr2iits3MFvzh6xxvr04KPNE4LBE9gEcvq0E0CkgrvUPldvS1\n\tZtRCd7h3Ts0eDn3eRAE0+ELbYcnkiDhoqfdd7RH8=","Date":"Thu, 5 Mar 2020 01:38:21 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200304233821.GF28814@pendragon.ideasonboard.com>","References":"<20200304232246.325384-1-niklas.soderlund@ragnatech.se>\n\t<20200304232246.325384-8-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200304232246.325384-8-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [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:38:24 -0000"}}]