Re: [PATCH 00/61] reduce use of rte_memcpy
From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2026-08-20 20:14:07
On Thu, 20 Aug 2026 16:00:53 +0200 Morten Brørup [off-list ref] wrote:
quoted
From: Konstantin Ananyev [mailto:konstantin.ananyev@huawei.com] Sent: Thursday, 20 August 2026 15.08quoted
quoted
quoted
About replacing rte_memcpy with memcpy()...quoted
From: Stephen Hemminger [mailto:stephen@networkplumber.org] Sent: Thursday, 20 August 2026 07.12 The DPDK function rte_memcpy() only exists as an optimization for shortcomings in performance of libc memcpy() on someplatforms.quoted
quoted
quoted
Yes, and those platforms should benefit from it. E.g. the vhost performance improvements for Haswell and Broadwell[1].quoted
Where similar performance improvements implemented in therelevantquoted
quoted
quoted
compilers (GCC, Clang, MSVC)? [1]:https://github.com/DPDK/dpdk/commit/4b42e90ef0e421dc777f2b2e377eb237cdquoted
quoted
quoted
3675fa IMO, performance should remain a high priority for DPDK.As I can read the series, good few of them do remove rte_memcpyfromquoted
quoted
the CP, where it is clearly irrelevant.Agree!quoted
For those on the DP, at least for some of them we can run perftests:quoted
quoted
let say for hash we do have perf_autotest which can be used tomeasurequoted
quoted
the perf diff. If there is none, or neglectable - then no point to keep rte_memcpy here.Unless that perf test is run on all platforms, the result only showsperf diff onquoted
the tested platforms.How this patch differs from all others?It removes something that is supposed to be a performance optimization. E.g. reference [1] fixes vhost performance on Haswell and Broadwell; if we remove rte_memcpy(), the performance of that use case on those CPU types might drop back to being bad.quoted
For each and every change we made in DPDK, to ensure that there is no perf regression introduced we rely on: 1) CI auto testing 2) manual testing from some platform vendors (once per release cycle) 3) good will of submitter to test the changes he produces as much as possible Obviously, yes we are not testing on each possible platform and yes, in theory some regressions can sneak in unseen. But that could happen with other patches too, so from my perspective - we just need our usual testing procedure here, if it shows no regression, the patch is good to go in.quoted
quoted
quoted
quoted
Many platforms have no special rte_memcpy() and just usememcpy().quoted
quoted
quoted
quoted
But many analysis and test tools know that memcpy() is aspecialquoted
quoted
quoted
quoted
case and check for overwrite, bounds errors etc. Thereforememcpy()quoted
quoted
quoted
quoted
should be preferred wherever possible.I think this is the only substantial benefit of replacingrte_memcpy() withquoted
memcpy()! Could we reap this benefit by having special builds for suchtools,quoted
quoted
wherequoted
rte_memcpy() is modified to use memcpy() instead? Then we wouldn't have to compromise on performance. Also, rte_memcpy() used to have a pragma disabling bounds checksduequoted
quoted
to somequoted
Intel drivers using [0] instead of []; the pragma was removedfromquoted
quoted
rte_memcpy()quoted
when the Intel drivers were fixed. I'm not sufficiently familiar with analysis/test tools to saywhatquoted
quoted
they can detectquoted
when using memcpy() instead of the copy methods used byrte_memcpy().quoted
quoted
quoted
quoted
This patch series introduces a coccinelle script to find calls to rte_memcpy() where size is fixed, and change them to regular memcpy(). This was the starting point for this cleanup. There is also some cleanups to include rte_memcpy.h andstring.hquoted
quoted
quoted
quoted
where needed. Often the includes were happening by some other header. And also removal of rte_memcpy.h where no longerneeded.quoted
quoted
quoted
quoted
The result is a 46% reduction in use of rte_memcpy. The remaining rte_memcpy can be cleaned up later: - drivers with active maintenance (like mlx5); - changes to rte_memcpy which need benchmarking; - test code for rte_memcpy can be removed as last step. No functional change, no warnings in all compilers includingLTO.quoted
quoted
quoted
memcpy() does not always use inline vector instructions for fixedsize copy [2].quoted
[2]:https://inbox.dpdk.org/dev/98CBD80474FA8B44BF855DF32C47DC35F659B8@smaquoted
quoted
rtserver.smartshare.dk/ Another disadvantage of rte_memcpy() is the lack of developerguidance.quoted
It is not well documented when to use rte_memcpy() and when tousequoted
quoted
memcpy().quoted
We discussed something similar on the Tech Board meetingyesterday;quoted
quoted
it is notquoted
well documented when to use which type of "ring" (normal, RTS,HTS),quoted
quoted
so maybequoted
we could remove one of them. But removing an option is not an improvement, if the removedoptionquoted
quoted
wouldquoted
have been the better choice for some use cases. PS: The general guidance for rte_memcpy() usage is somethinglike:quoted
quoted
quoted
rte_memcpy() only in fast path, memcpy() everywhere else, assignment "=" when copying fixed size structures.I suppose for te_memcpy() we can be even more strict: Use it only for DP, and only after measurement, that shows clear perf improvement over ordinal memcpy(). Alnd also ask contributors to document it (in the comments), i.e.: /* on <platform testsed> rte_memcpy() gives X% perf boost whendoingquoted
quoted
...*/ rte_memcpy(...);Disagree! DPDK has performance optimized libs and functions. Developers should not need to document that using a DPDK function isfasterquoted
than using a libc function. We don't require perf measurements for using DPDK rte_hash instead oflibcquoted
hashmap.Not sure what libc hashmap you are talking about? AFAIK such thing doesn't exist.. or you talking about c++ maps?Sorry, it was hashmap in libmba. Bad example.quoted
If so, then I think the analogy is not correct. Why not to remember another example when we get rid of our own hand-written atomics and barriers in favor of using atomics ones.Great example. IIRC, many people were involved in this effort, and it was thoroughly reviewed for correctness and performance. And some of the old atomics still ended up remaining for performance reasons. And C11 atomics is still not the default for DPDK. That level of effort doesn't seem to be on the table for migrating from rte_memcpy() to memcpy(). The vibe I'm sensing is more like: "Compilers' built-in memcpy() is just as good as rte_memcpy(), so rte_memcpy() has outlived itself." And maybe that statement is true, but I just don't feel confident about it. Perhaps I'm just being too cautious here.quoted
quoted
I agree about not using rte_memcpy() in the control plane. And I support Stephen's effort to clean this up. But why the eagerness to avoid using rte_memcpy() in the fast path?I think we are not talking about 'avoiding' but about 'limiting'. There are many cases, when people use rte_memcpy() just because 'it is used in other places, so it is probably better' In general memcpy() and rte_memcpy() have same syntax, provide same functionality, plus CC vendors made a good progress in optimizing memcpy(), so now for many cases it provides nearly the same or better performance. I think no-one forces to replace rte_memcpy() in places where it does provide better results, but for the cases when there is no perf difference, I think memcpy() should have precedence.You prefer memcpy() over rte_memcpy() when they perform similarly. That's your preference. And you are not alone with that preference. When they perform similarly, I prefer rte_memcpy(). And it seems I'm in the minority with that preference. If we set up barriers to using rte_memcpy(), we'll see even more custom implementations, such as in the ring [3] and stack [4] libraries. But maybe (and I'm being serious here!) that might be a good thing after all: Use memcpy() for general cases, and use individually specialized versions for special use cases. (Possibly using pragmas to tweak memcpy() for some of those special use cases.) [3]: https://elixir.bootlin.com/dpdk/v26.07/source/lib/ring/rte_ring_elem_pvt.h#L65 [4]: https://elixir.bootlin.com/dpdk/v26.07/source/lib/stack/rte_stack_std.h#L40 Here's an alternative path... PowerPC rte_memcpy() uses memcpy() for fixed size copies [5]. And ARM makes the rte_memcpy() implementation build time optional [6]. We could start softly by copying these two concepts to X86 architecture. [5]: https://elixir.bootlin.com/dpdk/v26.07/source/lib/eal/ppc/include/rte_memcpy.h#L80 [6]: https://elixir.bootlin.com/dpdk/v26.07/source/lib/eal/arm/include/rte_memcpy_64.h#L13
I used to think for DPDK performance should be the highest priority. Now I think the priorities need to be: - security. in the age of AI scanners, security has to come first. - performance. - architecture. code must be logical and readable as much as possible. - consistency. don't do special cases if not needed for 1,2,3 Also, no longer care if performance goes down for users using new releases on five year old tool chains. If they are on GCC over five years old (pre GCC 10) then the problem is really the tool set not DPDK.