Commit 1ede1556 authored by Mikhail Istomin's avatar Mikhail Istomin Committed by Commit Bot

Optimize ReadFileToStringWithMaxSize function

GetFileSize can be used to estimate buffer size if file size is
available. So use it as a hint for buffer size for file reading.
Also avoid latest fread syscall in reading loop using feof.

Bug: 821262
Change-Id: I7dc30483a2f95d4da2c0d3cb0049941d2634a281
Reviewed-on: https://chromium-review.googlesource.com/958861
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559168}
parent 557d8e0e
......@@ -136,27 +136,52 @@ bool ReadFileToStringWithMaxSize(const FilePath& path,
return false;
}
const size_t kBufferSize = 1 << 16;
std::unique_ptr<char[]> buf(new char[kBufferSize]);
size_t len;
size_t size = 0;
bool read_status = true;
// Many files supplied in |path| have incorrect size (proc files etc).
// Hence, the file is read sequentially as opposed to a one-shot read.
while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
if (contents)
contents->append(buf.get(), std::min(len, max_size - size));
if ((max_size - size) < len) {
// Hence, the file is read sequentially as opposed to a one-shot read, using
// file size as a hint for chunk size if available.
constexpr int64_t kDefaultChunkSize = 1 << 16;
int64_t chunk_size;
#if !defined(OS_NACL_NONSFI)
if (!GetFileSize(path, &chunk_size) || chunk_size <= 0)
chunk_size = kDefaultChunkSize - 1;
// We need to attempt to read at EOF for feof flag to be set so here we
// use |chunk_size| + 1.
chunk_size = std::min<uint64_t>(chunk_size, max_size) + 1;
#else
chunk_size = kDefaultChunkSize;
#endif // !defined(OS_NACL_NONSFI)
size_t bytes_read_this_pass;
size_t bytes_read_so_far = 0;
bool read_status = true;
std::string local_contents;
local_contents.resize(chunk_size);
while ((bytes_read_this_pass = fread(&local_contents[bytes_read_so_far], 1,
chunk_size, file)) > 0) {
if ((max_size - bytes_read_so_far) < bytes_read_this_pass) {
// Read more than max_size bytes, bail out.
bytes_read_so_far = max_size;
read_status = false;
break;
}
size += len;
// In case EOF was not reached, iterate again but revert to the default
// chunk size.
if (bytes_read_so_far == 0)
chunk_size = kDefaultChunkSize;
bytes_read_so_far += bytes_read_this_pass;
// Last fread syscall (after EOF) can be avoided via feof, which is just a
// flag check.
if (feof(file))
break;
local_contents.resize(bytes_read_so_far + chunk_size);
}
read_status = read_status && !ferror(file);
CloseFile(file);
if (contents) {
contents->swap(local_contents);
contents->resize(bytes_read_so_far);
}
return read_status;
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment