From: Zachary Turner Date: Thu, 25 May 2017 21:12:27 +0000 (+0000) Subject: Make BinaryStreamReader::readCString a bit faster. X-Git-Tag: llvmorg-5.0.0-rc1~4249 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95c625ecc9067f7215f476f44f01cb0cc0c24ba8;p=platform%2Fupstream%2Fllvm.git Make BinaryStreamReader::readCString a bit faster. Previously it would do a character by character search for a null terminator, to account for the fact that an arbitrary stream need not store its data contiguously so you couldn't just do a memchr. However, the stream API has a function which will return the longest contiguous chunk without doing a copy, and by using this function we can do a memchr on the individual chunks. For certain types of streams like data from object files etc, this is guaranteed to find the null terminator with only a single memchr, but even with discontiguous streams such as MappedBlockStream, it's rare that any given string will cross a block boundary, so even those will almost always be satisfied with a single memchr. This optimization is worth a 10-12% reduction in link time (4.2 seconds -> 3.75 seconds) Differential Revision: https://reviews.llvm.org/D33503 llvm-svn: 303918 --- diff --git a/llvm/lib/Support/BinaryStreamReader.cpp b/llvm/lib/Support/BinaryStreamReader.cpp index 5c27744..8622329 100644 --- a/llvm/lib/Support/BinaryStreamReader.cpp +++ b/llvm/lib/Support/BinaryStreamReader.cpp @@ -42,29 +42,30 @@ Error BinaryStreamReader::readBytes(ArrayRef &Buffer, uint32_t Size) { } Error BinaryStreamReader::readCString(StringRef &Dest) { - // TODO: This could be made more efficient by using readLongestContiguousChunk - // and searching for null terminators in the resulting buffer. - - uint32_t Length = 0; - // First compute the length of the string by reading 1 byte at a time. uint32_t OriginalOffset = getOffset(); - const char *C; + uint32_t FoundOffset = 0; while (true) { - if (auto EC = readObject(C)) + uint32_t ThisOffset = getOffset(); + ArrayRef Buffer; + if (auto EC = readLongestContiguousChunk(Buffer)) return EC; - if (*C == '\0') + StringRef S(reinterpret_cast(Buffer.begin()), Buffer.size()); + size_t Pos = S.find_first_of('\0'); + if (LLVM_LIKELY(Pos != StringRef::npos)) { + FoundOffset = Pos + ThisOffset; break; - ++Length; + } } - // Now go back and request a reference for that many bytes. - uint32_t NewOffset = getOffset(); + assert(FoundOffset >= OriginalOffset); + setOffset(OriginalOffset); + size_t Length = FoundOffset - OriginalOffset; if (auto EC = readFixedString(Dest, Length)) return EC; - // Now set the offset back to where it was after we calculated the length. - setOffset(NewOffset); + // Now set the offset back to after the null terminator. + setOffset(FoundOffset + 1); return Error::success(); }