NULL terminated string and its length
I have a legacy code that receives some proprietary, parses it and creates a bunch of static开发者_运维知识库 char arrays (embedded in class representing the message), to represent NULL strings. Afterwards pointers to the string are passed all around and finally serialized to some buffer.
Profiling shows that str*()
methods take a lot of time.
Therefore I would like to use memcpy()
whether it's possible. To achive it I need a way to associate length with pointer to NULL terminating string. I though about:
Using
std::string
looks less efficient, since it requires memory allocation and thread synchronization.I can use
std::pair<pointer to string, length>
. But in this case I need to maintain length "manually".
What do you think?
use std::string
Profiling shows that str*() methods take a lot of time
Sure they do ... operating on any array takes a lot of time.
Therefore I would like to use memcpy() whether it's possible. To achive it I need a way to associate length with pointer to NULL terminating string. I though about:
memcpy
is not really any slower than strcpy
. In fact if you perform a strlen
to identify how much you are going to memcpy
then strcpy
is almost certainly faster.
Using std::string looks less efficient, since it requires memory allocation and thread synchronization
It may look less efficient but there are a lot of better minds than yours or mine that have worked on it
I can use std::pair. But in this case I need to maintain length "manually".
thats one way to save yourself time on the length calculation. Obviously you need to maintain the length manually. This is how windows BSTR
s work, effectively (though the length is stored immediately prior, in memory, to the actual string data). std::string
. for example, already does this ...
What do you think?
I think your question is asked terribly. There is no real question asked which makes answering next to impossible. I advise you actually ask specific questions in the future.
Use std::string
. It's an advice already given, but let me explain why:
One, it uses a custom memory allocation scheme. Your char*
strings are probably malloc'ed. That means they are worst-case aligned, which really isn't needed for a char[]
. std::string
doesn't suffer from needless alignment. Furthermore, common implementatios of std::string
use the "Small String Optimization" which eliminates a heap allocation altogether, and improves locality of reference. The string size will be on the same cache line as the char[]
itself.
Two, it keeps the string length, which is indeed a speed optimization. Most str*
functions are slower because they don't have this information up front.
A second option would be a rope
class, e.g. from SGI. This be more efficient by eliminating some string copies.
Your post doesn't explain where the str*()
function calls are coming from; passing around char *
certainly doesn't invoke them. Identify the sites that actually do the string manipulation and then try to find out if they're doing so inefficiently. One common pitfall is that strcat
first needs to scan the destination string for the terminating 0 character. If you call strcat
several times in a row, you can end up with a O(N^2) algorithm, so be careful about this.
Replacing strcpy
by memcpy
doesn't make any significant difference; strcpy
doesn't do an extra pass to find the length of the string, it's simply (conceptually!) a character-by-character copy that stops when it encounters the terminating 0. This is not much more expensive than memcpy
, and always cheaper than strlen
followed by memcpy
.
The way to gain performance on string operations is to avoid copies where possible; don't worry about making the copying faster, instead try to copy less! And this holds for all string (and array) implementations, whether it be char *
, std::string
, std::vector<char>
, or some custom string / array class.
What do I think? I think that you should do what everyone else obsessed with pre-optimization does. You should find the most obscure, unmaintainable, yet intuitively (to you anyway) high-performance way you can and do it that way. Sounds like you're onto something with your pair<char*,len>
with malloc/memcpy idea there.
Whatever you do, do NOT use pre-existing, optimized wheels that make maintenence easier. Being maintainable is simply the least important thing imaginable when you're obsessed with intuitively measured performance gains. Further, as you well know, you're quite a bit smarter than those who wrote your compiler and its standard library implementation. So much so that you'd be seriously silly to trust their judgment on anything; you should really consider rewriting the entire thing yourself because it would perform better.
And ... the very LAST thing you'll want to do is use a profiler to test your intuition. That would be too scientific and methodical, and we all know that science is a bunch of bunk that's never gotten us anything; we also know that personal intuition and revelation is never, ever wrong. Why waste the time measuring with an objective tool when you've already intuitively grasped the situation's seemingliness?
Keep in mind that I'm being 100% honest in my opinion here. I don't have a sarcastic bone in my body.
精彩评论