But I guess these people have run the benchmarks. ...Or maybe not. I have to wonder.
But I guess these people have run the benchmarks. ...Or maybe not. I have to wonder.
Modern CPUs have branch prediction.
The predictors work by caching which branches were taken, and assuming the same outcome is likely to happen next time the branch at that address is checked. That particular branch is checked all the time, and unless you actually have >2GB strings the result is always the same.
Only branches which dynamic runtime behavior are bad for performance, like binary search when the same branch is taken/not taken randomly, depending on the data and the key being searched. Branches with stable runtime behavior are OK thanks to branch prediction. Examples of good branches: `while( i < 10000 )`, `if( string_length < INT_MAX )`
Consider the implications to inlining: the size getter is a prime candidate, but suddenly it gets less predictor-friendly.
Edit: this is naturally a good case for manual hinting.
struct not_too_long_string {
char* data;
uint32_t size;
uint32_t capacity;
};
Of course, if you do it that way then the longest string you can store with the small string optimization is probably ~15 bytes instead of ~23. So although you do save 1/3 on the size of each string, on average you're probably still going to end up doing a greater number of dynamic allocations because of the reduced small string capacity. Unless of course you know a priori that a sufficiently large portion of your strings will be > 15 bytes anyway, which of course the implementors of std::string almost certainly don't know.Edit: I failed to notice the part about the length being in the data block (doh). I guess the disadvantage to putting the length there would be that an extra indirection is required to get the length, a rather common operation. And as others have pointed out, that only saves 4 bytes, which will be used anyway for alignment..
It would require an additional branch to test for huge strings, but it will be almost never executed, and I think modern CPUs are pretty good at optimizing out such branches...