1

I want know what the fastest function for copy n bytes from *source to *destination, when *destination = *source + k, and k is netural or zero.

The memcpy() function has undefind behavior for overlapping.

The memmove() function is not the best, since it has to check the overlapping side.

There is another function that is optimal to my case?

Thanks in advance!

  • 1
    *Why* is `memmove` "not the best"? – user2864740 Apr 17 '14 at 00:02
  • What does "k is neutral" mean? – Michael Burr Apr 17 '14 at 00:05
  • You may be interested in the comment thread on this glibc bug report from a couple years ago about the merits of having memory copy functions that depend on the relative position of `dest` and `src` as a pre-condition for proper operation: https://sourceware.org/bugzilla/show_bug.cgi?id=12518 I'd suggest just using `memmove()` - what is a correct positioning of `dest` and `src` today becomes a different positioning in several months when the code is modified by someone unaware of the importance of what is nearly always a minor detail taken care of by the compiler, linker, or OS. – Michael Burr Apr 17 '14 at 00:28
  • @user2864740 `memmove` has to correct position of the `source` and `dest` in order to prevent the overlapping problem. That's unnecessary in my case. –  Apr 17 '14 at 06:29
  • @MichaelBurr That's mean that I want to call the function like that: `memcpy(*source + 2, *source, 3)` –  Apr 17 '14 at 06:33
  • @MichaelBurr I want my code behavior well defined, and maximum performance. Using `memmove()` doesn't give the maximum performance. –  Apr 17 '14 at 06:36

2 Answers2

3

memmove() is fine. It will figure out the direction of the move on its own by comparing the two pointers — an implementation might look something like:

void * memmove(void *dst, const void *src, size_t len)
{
    intptr_t dsti = dst;
    intptr_t srci = src;
    if (src > dst) {
        return _memmove_up(dst, src, len);
    } else {
        return _memmove_down(dst, src, len);
    }
 }

On most CPUs, this will compile to perhaps a half dozen extra instructions, which are only executed once when the function is called — there is no benefit to bypassing this.

(In theory, there is no reason why memcpy() should not be able to do a similar comparison itself to remove the distinction between it and memmove(). However, for some unfortunate historical reason, the authors of the C standard library did not decide to make this simplification, so we're stuck with these two functions.)

  • 2
    All it has to do to check is compare the pointers, though — that's a very simple operation for it to perform. –  Apr 17 '14 at 00:02
  • 1
    If you're calling it many times in the same situation, the check will be a correctly-predicted branch and probably consumes zero cycles. – R.. GitHub STOP HELPING ICE Apr 17 '14 at 00:56
  • @duskwuff Thanks. In your code, I want the `_memmove_down()` function. The comparison is unnecessary, and may decrease the performance quality, as explained @R.. @R.. Thanks.. –  Apr 17 '14 at 06:44
  • 1
    The comparison will take a matter of a few clock cycles. It's completely insignificant. –  Apr 17 '14 at 07:03
2

memmove() has to spend some time determining how and whether the source and target overlap, so it can decide the order in which to copy the data.

Hypothetically, a version of memmove() that omits this initial calculation, either because it assumes a particular direction or because it has an extra parameter that lets you tell it, might be a little faster than memmove().

But there is no such function in the standard library.

You could write your own function, but it's unlikely that it would be as fast as your system's memmove(), which is very likely to be heavily optimized. You could grab a copy of the source code for your system's memmove() function (if it's available) and modify it, but the result would likely be non-portable (memmove() can depend on the characteristics of the system it's running on).

But it's very unlikely that it would be worth the effort. The time memmove() spends doing the initial calculation is, for moves of reasonable size, likely to be a small fraction of the time spent copying the data.

Unless you know from actual measurement that the initial computation performed by memmove() carries a significant performance penalty for your program, just use memmove() itself.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631