News for hackers. Stuff that matters.
Re:C performance mystery: delete unused string constant by dzdt on Wednesday June 24, 2020 @05:28PM (#23634080)
Lots of performance mysteries, particularly in micro-benchmarks, are explained by how either code or data aligns to memory cache lines. A seemingly unrelated change will cause memory locations to move. No idea if that is the case here or not but it looks like a possibility.
Re:C performance mystery: delete unused string constant by userbinator on Wednesday June 24, 2020 @07:42PM (#23635148)
This is one of the reasons why I think microbenchmarks are either not very useful or completely misleading --- they'll favour things like insanely unrolled loops or aligned data with lots of padding, when in fact on a macro-scale those things will certainly affect performance negatively due to cache misses.

My preferred approach when optimising is to go for size first; then if more speed is desired, carefully apply size-increasing optimisations to areas which may benefit, testing with a macro benchmark to judge any improvement.

Re:C performance mystery: delete unused string constant by YZF on Wednesday June 24, 2020 @08:59PM (#23635669)
If the macro scale is dominated by the code you're optimizing, which is often the case, let's say some inner loops of a codec, signal processing, etc. then the cache misses that may follow aren't really a concern. Obviously(?) taking some random code that doesn't run frequently and trying to optimize it won't make a difference. Microbenchmarks are pretty useful in this context since they let you iterate faster. More generally the question is what is the bottleneck, if the bottleneck is fetching stuff into caches then that's what you optimize for, if the bottleneck is some computation that is running from caches then that's what you optimize...
Re:C performance mystery: delete unused string constant by jeffbee on Wednesday June 24, 2020 @09:27PM (#23635870)
The big cautionary tale of microbenchmarking is memcpy. If you look at the Gnu memcpy, it's ridiculously long and obviously been guided by extensive benchmarking. And memcpy often shows up in profiles, so it is a big target. But in real systems a small simple loop will perform better due to icache pressure.
Re:C performance mystery: delete unused string constant by makapuf on Thursday June 25, 2020 @03:10AM (#23637727)
Memcpy lights not be a good example however because it's often replaced by a loop (or a move or eliminated altogether) by the compiler, because it's such a commun function that its understood by the compiler, and the tradeoff of the real function are also understood and taken into account (of course I'm sure there are bad optimizations)
Re:C performance mystery: delete unused string constant by MaxBarraclough on Thursday June 25, 2020 @04:56AM (#23638410)
> in real systems a small simple loop will perform better due to icache pressure

Do you have a source for this? Seems surprising GCC would leave such low-hanging fruit. G++ makes the effort to reduce std::copy to a memmove call when it can, or at least some of the time when it can (or at least, it did so in 2011). [0]

Related to this: does GCC treat memcpy differently when it can determine at compile-time that it's just a small copy?

[0] https://stackoverflow.com/a/4707028/

Re:C performance mystery: delete unused string constant by Gibbon1 on Thursday June 25, 2020 @04:23PM (#23645237)
Problem is superscalar processors the correspondence between number of instructions and speed breaks down. Partly because the processor does it's own optimization on the fly and can do multiple things in parallel.

A programmer should be careful about second guessing the compiler. And a compiler should be careful about second guessing the processor.

Re:C performance mystery: delete unused string constant by MaxBarraclough on Friday June 26, 2020 @04:42AM (#23649967)
I'm not sure if you're implying this is premature optimisation. It isn't.

It's a performance-sensitive standard-library function, the kind of thing that deserves optimisation in assembly. It's also the kind of problem that can be accelerated with SIMD, but that necessarily means more complex code. That's why the standard library implementations aren't always dead simple.

Here's a pretty in-depth discussion [0]. They discuss CPU throttling, caches, and being memory-bound.

[0] https://news.ycombinator.com/item?id=18260154

Re:C performance mystery: delete unused string constant by jeffbee on Thursday June 25, 2020 @11:55AM (#23642095)
Only personal experience. If you look at the memcpy in llvm's libc, it was contributed by Googlers who share my experience and perspective.
Re:C performance mystery: delete unused string constant by api on Wednesday June 24, 2020 @09:52PM (#23636033)
It's amazing to me that every CPU doesn't have specialized memory copying instructions given how common an operation this is and how it can be a bottleneck. We have hundreds of vector instructions to optimize all kinds of special cases but little for this most general thing?
Re:C performance mystery: delete unused string constant by jeffbee on Wednesday June 24, 2020 @10:05PM (#23636107)
Intel has `rep movs` which is recommended for general use, you can beat it for sizes < 128B using a specialized loop. A very good memcpy for general purposes would just branch over the size to either a specialized small copy or `rep movs` for larger sizes.

The GCC version is just bananas. https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysde...

Compare the newer ERMS implementation: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86...

Re:C performance mystery: delete unused string constant by andrewf on Wednesday June 24, 2020 @11:42PM (#23636670)
What's weird is that if you git blame a bit, a lot of the elaborate stuff was contributed by Intel.
Re:C performance mystery: delete unused string constant by jeffbee on Wednesday June 24, 2020 @11:53PM (#23636734)
Intel is at least as guilty of chasing misleading benchmarks as anyone else in the history of our field.
Re:C performance mystery: delete unused string constant by saagarjha on Thursday June 25, 2020 @04:11AM (#23638097)
No AVX2-optimized version? I'm disappointed…

Edit: it's rolled into the erms version.

Re:C performance mystery: delete unused string constant by userbinator on Wednesday June 24, 2020 @10:04PM (#23636100)
x86 does, it's called REP MOVS, and it copies entire cachelines at a time (if the size of the copy lets it.) AFAIK it has done this since the P6 family (Pentium II), and has only gotten better over time. As a bonus, it is only 2 bytes long. I believe the Linux kernel uses it as its default memcpy()/memmove().

Here's some very interesting discussion about it: https://stackoverflow.com/questions/43343231/enhanced-rep-mo...

Re:C performance mystery: delete unused string constant by unscaled on Thursday June 25, 2020 @03:39AM (#23637889)
It's funny enough that the REP family of instructions has existed at least since the original 8086/8088. It's very much a relic of the CISC heritage of the x86 ISA, and it was probably meant to make writing assembly code easier and to save space - rather to improve performance.

I remember it was actually quite common in early PC programs, but I don't remember well enough whether it was also generated by compilers, or just existed in hand-optimized assembly (which was of course extremely common back then).

Re:C performance mystery: delete unused string constant by api on Wednesday June 24, 2020 @10:09PM (#23636142)
Why isn't it the default everywhere?
Re:C performance mystery: delete unused string constant by jeffbee on Wednesday June 24, 2020 @10:18PM (#23636203)
As I tried to indicate, the microbenchmark-guided unrolled loops look better than the simple `rep` instruction because the benchmarks aren't realistic. They don't suffer from mispredicted branches, they don't experience icache pressure. Basically the microarchitectural reality is absent in a small benchmark.

There's also the fact that `rep` startup cost was higher in the past than it is now. I think it started to get really fast around Ivy Bridge.

This is all discussed in Intel's optimization manual, by the way.

Re:C performance mystery: delete unused string constant by xelxebar on Wednesday June 24, 2020 @11:05PM (#23636475)
Neat. I was unaware of this manual. For the lazy but curious:

https://software.intel.com/content/www/us/en/develop/downloa...

And if you want ALL THE THINGS:

https://software.intel.com/content/www/us/en/develop/article...

Re:C performance mystery: delete unused string constant by yvdriess on Thursday June 25, 2020 @03:57AM (#23638017)
Yes, some compilers emit AVX move instructions on memcpy or compiler-generated moves (e.g. pass by value struct). (In addition to the rep move mentioned in the sibling posts)
Re:C performance mystery: delete unused string constant by ckennelly on Thursday June 25, 2020 @12:31AM (#23636929)
llvm-libc's memcpy is heavily sized optimized for this reason. A dedicated instruction that is fast for all cases, is ideal, though.
Re:C performance mystery: delete unused string constant by GuB-42 on Wednesday June 24, 2020 @11:16PM (#23636540)
> My preferred approach when optimising is to go for size first

Agreed, in my experience, more often than not, size is speed. Small memory usage mean less cache misses, smaller memcpys, more chance of having data fit a single word, etc...

Re:C performance mystery: delete unused string constant by scoutt on Thursday June 25, 2020 @03:51AM (#23637967)
Except when loops unrolls make things faster.
Re:C performance mystery: delete unused string constant by ants_a on Thursday June 25, 2020 @05:02AM (#23638457)
That only tends to be the case for tiny loops where loop iterator updates can be folded into addressing displacements and that frees up an execution port needed for something else.

If you don't know what you are doing unrolling is just as likely to hurt performance because you don't fit into uOP cache and get less decode bandwidth as a result. Or you increase ICache pressure on macro benchmarks and hurt real world performance. Modern cores are really good at hiding loop accounting overhead.

Re:C performance mystery: delete unused string constant by scoutt on Thursday June 25, 2020 @08:29AM (#23639876)
In a world where all the electronic devices are composed of x86 cores and/or have a data and/or instruction cache, it could be true.

But there are plenty of architectures out there where space-time tradeoffs (by optimized compilers) are still a thing (my PoV is from the embedded industry).

Re:C performance mystery: delete unused string constant by jhallenworld on Wednesday June 24, 2020 @09:41PM (#23635965)
I've found an interesting converse with macro benchmarks: small improvements to any of the top functions shown in your profiler output will have a relatively larger than expected effect on the overall speed. I mean you make a change that improves just one function by a little bit on its own (within the benchmark), but the overall is better than this. I think you end up freeing resources used by everything else.

The trick is to optimize the right macro benchmark- one that matches your customer's key use case I suppose.

Re:C performance mystery: delete unused string constant by nwallin on Wednesday June 24, 2020 @06:19PM (#23634518)
This is probably the answer.

I watched a great talk about this, and how to avoid problems that result from it. The presenter built a framework that made random changes to alignment of various blocks of code with two different versions of the same microbenchmark until it had high statistical confidence that either one was faster than the other, or it would eject and say that the difference between the two was statistically insignificant. Or something along those lines.

I'm looking for the video now, but I can't find it. Pretty sure it was CppCon but I'm not positive.

Re:C performance mystery: delete unused string constant by moonchild on Wednesday June 24, 2020 @06:23PM (#23634558)
Possibly 'Performance Matters'? (https://www.youtube.com/watch?v=r-TLSBdHe1A)
Re:C performance mystery: delete unused string constant by dkersten on Wednesday June 24, 2020 @06:29PM (#23634604)
This was the very first thing I thought of when I saw this submission title! Great talk, well worth watching.
Re:C performance mystery: delete unused string constant by Twirrim on Thursday June 25, 2020 @02:20AM (#23637469)
My team watched this several months ago now. "Eyeball statistics" he mentions at one stage has been a phrase that has particularly stuck for us from it. So many metrics dashboards etc rely on it to a disturbing degree, if you step back and really think about what it's _actually_ showing you. I almost want to put a warning banner on most of ours. "Beware Eyeball Statistics!"
Re:C performance mystery: delete unused string constant by nwallin on Thursday June 25, 2020 @10:17PM (#23648038)
The other one is 99th percentile latency. Lots of people think of 99th percentile latency as the latency that 1% of their users will encounter. But if your site loads 200 assets, almost every site load will hit 99th percentile latency.
Re:C performance mystery: delete unused string constant by nwallin on Thursday June 25, 2020 @10:08PM (#23648000)
Yup! That's the one!
Re:C performance mystery: delete unused string constant by kristjansson on Wednesday June 24, 2020 @06:20PM (#23634523)
Re:C performance mystery: delete unused string constant by kristjansson on Wednesday June 24, 2020 @06:19PM (#23634519)
This[1] talk from Emery Berger at last year's Strange Loop does a good job discussing the impact of alignment and other 'small' changes on performance, and how to estimate the actual impact of changes on performance

[1]: https://www.youtube.com/watch?v=r-TLSBdHe1A

Re:C performance mystery: delete unused string constant by codezero on Wednesday June 24, 2020 @05:32PM (#23634107)
Yep, I'm not even a hobbyist in this area, and immediately wondered if there was an alignment change because of it.

With that said, it sounds like at least with GCC, a global constant would go in the TEXT section of the binary and I can't think of why that would affect performance, especially since the variable was seemingly unused. Neat, I hope someone finds the thread to pull here :)

Re:C performance mystery: delete unused string constant by tom_mellior on Wednesday June 24, 2020 @06:01PM (#23634371)
> it sounds like at least with GCC, a global constant would go in the TEXT section of the binary

I don't know why you think it sounds like that, but GCC (on Linux) puts global constants into the .rodata section (read-only data) and other global variables into the .data section.

> I can't think of why that would affect performance, especially since the variable was seemingly unused.

I'm guessing data alignment and corresponding changes in cache hits and misses. But I wonder if there's a scenario where this change changes the offsets of other variables from the base of the data section, which changes the encodings and therefore the sizes of the instructions accessing those variables, which overall changes code size and might cause code alignment issues. Probably too far-fetched.

Re:C performance mystery: delete unused string constant by vivekseth on Wednesday June 24, 2020 @06:17PM (#23634495)
On macOS, "gcc" puts strings that don't include a null byte in the TEXT section. I put quotes around gcc, since it seems that by default macOS aliases gcc to clang.

You can run the program I built here to see for your self: https://github.com/vivekseth/blog-posts/tree/master/Jump-Add...

Since the string in the TEXT section, we can actually execute it as if it were code!

After you build the program you can run `otool -t ./a.out` to verify that the string `execString` is indeed in the TEXT section.

Re:C performance mystery: delete unused string constant by tom_mellior on Wednesday June 24, 2020 @06:38PM (#23634659)
Interesting. And if you put a null byte at the end of that character array, it would put it in a different section? I don't have access to MacOS, but I would be interested in seeing the output of clang -S on that code (with and without a null byte), maybe you could add it to the repository?
Re:C performance mystery: delete unused string constant by vivekseth on Wednesday June 24, 2020 @07:37PM (#23635105)
If I'm remembering correctly (this was from 3 years ago), the string was moved to a different section if it had a null byte in the middle of the string. That's why coming up with the assembly I used was kinda tricky.

Here's the output as-is: https://gist.github.com/vivekseth/20f319d2a9978af57d926b649a...

Here's the output with a null byte in the middle: https://gist.github.com/vivekseth/fc50319aaac24588bcf568209b...

From what I can tell, it seems like both strings are in the TEXT section now. Maybe something changed, or I'm remembering incorrectly.

Re:C performance mystery: delete unused string constant by codezero on Wednesday June 24, 2020 @06:24PM (#23634568)
Thanks for the correction, hopefully my statement that I'm hardly a hobbyist makes it clear I'm not super sure :)

I guess I don't understand enough about how this variable sitting in memory might affect hit/miss/alignment especially if it's not used in the program as it's running.

Would it be that some variable that is used is pushed off of a page in memory or something by the unused variable, so access it is slower? I guess that makes sense.

Re:C performance mystery: delete unused string constant by kijiki on Wednesday June 24, 2020 @05:52PM (#23634289)
> ...a global constant would go in the TEXT section of the binary...

Wouldn't it go into the .rodata section, not .text?

Re:C performance mystery: delete unused string constant by codezero on Wednesday June 24, 2020 @05:55PM (#23634307)
I'm not sure, I am parroting what I thought I read on SO - so you are much more likely to be right, sorry about that!
Re:C performance mystery: delete unused string constant by vivekseth on Wednesday June 24, 2020 @06:25PM (#23634576)
clang seems to work this way, and macOS aliases gcc -> clang by default. Wrote more about this here: https://news.ycombinator.com/item?id=23634495
Re:C performance mystery: delete unused string constant by codezero on Wednesday June 24, 2020 @08:53PM (#23635631)
Thanks! Glad there's an explanation for my confusion :)
Re:C performance mystery: delete unused string constant by albertzeyer on Thursday June 25, 2020 @04:19AM (#23638160)
But if this is the reason, does it make sense to leave it in then? I.e. to unroll this here: https://github.com/google/wuffs/commit/6537a817b7f8351cded87...

I guess, maybe once another global constant is introduced somewhere else, this might have exactly the same effect.

But also, once there are more unrelated changes, everything will change anyway again.

It seems strange then to keep this in because right now this seems to help.

Re:C performance mystery: delete unused string constant by lmilcin on Thursday June 25, 2020 @06:09AM (#23638881)
I have worked on algorithmic trading where you basically stare at instructions and try to ensure the CPU does not stall on branches, that memory is accessed in a strided pattern recognizable to the CPU and that there are no more concurrent patterns that CPU can coordinate, that memory written does not by accident belong to another core, etc.

What is "mystery" in the article is actually bread and butter of anybody who tasked to seriously optimize a piece of non-trivial code.

Re:C performance mystery: delete unused string constant by guerrilla on Thursday June 25, 2020 @04:03AM (#23638053)
I'm pretty sure this is it. Changing the number of pointers shouldn't matter as they're already aligned but the string is an odd number of characters, which would change the offset of pretty much every other constant string and thus the performance of the respective lookups. They were probably just very lucky that it was aligned so well before removing it.
Re:C performance mystery: delete unused string constant by muth02446 on Wednesday June 24, 2020 @05:33PM (#23634123)
Re:C performance mystery: delete unused string constant by staycoolboy on Wednesday June 24, 2020 @08:33PM (#23635485)
That was my first thought. Not sure what compiler OP is using but I would put "#pragma align" all over the place and see if the absence still makes a difference.
Re:C performance mystery: delete unused string constant by guerrilla on Thursday June 25, 2020 @04:07AM (#23638072)
That wouldn't help if they're generating ELF files as .rodata is a string table, meaning it's tightly packed and as far as I know neither clang nor gcc pads it.
Re:C performance mystery: delete unused string constant by staycoolboy on Thursday July 02, 2020 @10:24PM (#23720480)
Ah, I didn't think of that.