views:

418

answers:

7
+4  Q: 

faster strlen ?

Typical strlen() traverse from first character till it finds \0. This requires you to traverse each and every character. In algorithm sense, its O(N).

Is there any faster way to do this where input is vaguely defined. Like: length would be less than 50, or length would be around 200 characters.

I thought of lookup blocks and all but didn't get any optimization.

+16  A: 

Sure. Keep track of the length while you're writing to the string.

Bob Aman
+1: Hooray pascal!
Stephen Canon
+1: Hooray Fortran (and don't allow to change it in any way after the declaration)
Stefano Borini
i did large improvements on strcat using this technique
Arabcoder
Bob, most of the time, its possible to maintain explicit length when we are writing string. Sometimes, its not possible :( For exa: reading stream from file or network. I might have got 500 characters but only first 200 character makes valid string and remaining 300 are not useful
Jack
That... doesn't sound right to me. Most situations involving file/network IO give you back the number of bytes read.
Bob Aman
Yes, they do give numbers of byte read. What if I am not interested in all of them but need just first valid string?
Jack
As in, you're trying to read only up to `\0`?
Bob Aman
YES.Also, please understand that not all programs behave the way you want. You might get this string from other process/machine where you don't have much of control.In general, my intention was to improve strlen prototype.
Jack
If that's what you're trying to do, then no, it's not possible to do better than O(n). `strlen` is what you want.
Bob Aman
+0: Hooray COBOL! (+0 because I'm not registered :( )
slacker
+5  A: 

The short answer: no.

The longer answer: do you really think that if there were a faster way to check string length for barebones C strings, something as commonly used as the C string library wouldn't have already incorporated it?

Without some kind of additional knowledge about a string, you have to check each character. If you're willing to maintain that additional information, you could create a struct that stores the length as a field in the struct (in addition to the actual character array/pointer for the string), in which case you could then make the length lookup constant time, but would have to update that field each time you modified the string.

Amber
Then we'd have Pascal strings all over again. :)
Wade Williams
But we'd probably have fewer buffer overflows (if they were either built-in to the language or used consistently) - which would be a Good Thing!
Jonathan Leffler
+8  A: 

Obviously, if your string has a known minimum length, you can begin your search at that position.

Beyond that, there's not really anything you can do; if you try to do something clever and find a \0 byte, you still need to check every byte between the start of the string and that point to make sure there was no earlier \0.

That's not to say that strlen can't be optimized. It can be pipelined, and it can be made to process word-size or vector chunks with each comparison. On most architectures, some combination of these and other approaches will yield a substantial constant-factor speedup over a naive byte-comparison loop. Of course, on most mature platforms, the system strlen is already implemented using these techniques.

Stephen Canon
+2  A: 

You can try to use vectorization. Not sure if compiler will be able perform it, but I did it manually (using intrinsics). But it could help you only for long strings.

Use stl strings, it's more safe and std::string class contains its length.

Elalfer
How would vectorization help? Even if the buffer was, say, 4 KB, there's no guarantee about the contents of the string after the first null, so if the vectorization started 4 operations (threads?) on the 1 KB boundaries, there's no telling what the three starting from a non-zero offset would see. I suppose the result would have to be the minimum of the 4 returned values - where the non-zero offset threads would have to add their starting position to the returned length.
Jonathan Leffler
I think Elalfer is proposing to assign each consecutive byte to a vector to be checked as a whole, and then scrolling the string scan of the length of the vector. That would definitely work, assuming you have a vector-based architecture.
Stefano Borini
@Jonathan Vectorization is not using threads! Vectorization means using the SIMD programming model to check consecutive bytes for zero simultaneously. http://en.wikipedia.org/wiki/SIMD It helps that vector alignment always make them fit in a single page. This implementation typically overflows the buffer but that is not caught by the MMU. We find these benign buffer overflows in the analyzer I work on. See also http://tsunanet.net/~tsuna/strlen.c.html for an impressive C implementation without special vector instructions.
Pascal Cuoq
@Jonathan: There is for example the "pcmpeqb" instructions, which compares 16 bytes at once. Additionally SSE 4.2 contains specific vector extensions for strings, like "pcmpistri". This has nothing to to with threading.
drhirsch
+3  A: 

Jack,

strlen works by looking for the ending '\0', here's an implementation taken from OpenBSD:

size_t
strlen(const char *str)
{
        const char *s;

        for (s = str; *s; ++s)
                ;
        return (s - str);
}

Now, consider that you know the length is about 200 characters, as you said. Say you start at 200 and loop up and down for a '\0'. You've found one at 204, what does it mean? That the string is 204 chars long? NO! It could end before that with another '\0' and all you did was look out of bounds.

Eli Bendersky
Thanks for answer. As I said, length is vaguely predicted and may not end after character 200.Also, if we start reading after 200th character, we might be reading invalid string (if string has ended around 100 character...)
Jack
Link also says same: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlen.c?annotate=1.7
Jack
+10  A: 

Actually, glibc's implementation of strlen is an interesting example of the vectorization approach. It is peculiar in that it doesn't use vector instructions, but finds a way to use only ordinary instructions on 32 or 64 bits words from the buffer.

Pascal Cuoq
very clever indeed!
ammoQ
On the other hand, at least on x86/x86_64 and gcc, you'll just get the compiler's builtin anyway.
LnxPrgr3
Yes, you have to give it another name if you want to make sure the version used is yours. If you are going to do this, you might as well somehow ensure that all strings your version will be passed are word-aligned (if possible) and remove the initial char-by-char loop completely.
Pascal Cuoq
+2  A: 

Get a Core i7 processor.

Core i7 comes with the SSE 4.2 instruction set. Intel added four additional vector instructions to speed up strlen and related search tasks.

Here are some interesting thoughts about the new instructions:

http://smallcode.weblogs.us/oldblog/2007/11/

Nils Pipenbrinck
Thanks for answer. As George Verghese says, hardware boost always helps :)
Jack