diff options
author | hashimoto <hashimoto@chromium.org> | 2015-04-27 22:27:19 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-28 05:27:22 +0000 |
commit | 1ad9bfe4e302fd57bbffd45ec9ad248893a7b2ba (patch) | |
tree | e672df9cc214415b6abfd505e002918538da7a22 | |
parent | 21999efe098e256c5b2099f450d155e6d48a4cd8 (diff) | |
download | chromium_src-1ad9bfe4e302fd57bbffd45ec9ad248893a7b2ba.zip chromium_src-1ad9bfe4e302fd57bbffd45ec9ad248893a7b2ba.tar.gz chromium_src-1ad9bfe4e302fd57bbffd45ec9ad248893a7b2ba.tar.bz2 |
Avoid copying the data string when posting ImportantFileWriter write tasks
When binding the data string to a callback, the existing code copies the data which can be 1MB+ sometimes.
Use scoped_ptr to avoid unnecessary data copy.
BUG=None
Review URL: https://codereview.chromium.org/1079943002
Cr-Commit-Position: refs/heads/master@{#327234}
-rw-r--r-- | base/files/important_file_writer.cc | 30 | ||||
-rw-r--r-- | base/files/important_file_writer.h | 4 | ||||
-rw-r--r-- | base/files/important_file_writer_unittest.cc | 8 | ||||
-rw-r--r-- | components/bookmarks/browser/bookmark_storage.cc | 6 |
4 files changed, 26 insertions, 22 deletions
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc index 47b0b09..f49790c 100644 --- a/base/files/important_file_writer.cc +++ b/base/files/important_file_writer.cc @@ -51,6 +51,12 @@ void LogFailure(const FilePath& path, TempFileFailure failure_code, << " : " << message; } +// Helper function to call WriteFileAtomically() with a scoped_ptr<std::string>. +bool WriteScopedStringToFileAtomically(const FilePath& path, + scoped_ptr<std::string> data) { + return ImportantFileWriter::WriteFileAtomically(path, *data); +} + } // namespace // static @@ -139,9 +145,9 @@ bool ImportantFileWriter::HasPendingWrite() const { return timer_.IsRunning(); } -void ImportantFileWriter::WriteNow(const std::string& data) { +void ImportantFileWriter::WriteNow(scoped_ptr<std::string> data) { DCHECK(CalledOnValidThread()); - if (data.length() > static_cast<size_t>(kint32max)) { + if (data->length() > static_cast<size_t>(kint32max)) { NOTREACHED(); return; } @@ -149,13 +155,14 @@ void ImportantFileWriter::WriteNow(const std::string& data) { if (HasPendingWrite()) timer_.Stop(); - if (!PostWriteTask(data)) { + auto task = Bind(&WriteScopedStringToFileAtomically, path_, Passed(&data)); + if (!PostWriteTask(task)) { // Posting the task to background message loop is not expected // to fail, but if it does, avoid losing data and just hit the disk // on the current thread. NOTREACHED(); - WriteFileAtomically(path_, data); + task.Run(); } } @@ -173,9 +180,9 @@ void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) { void ImportantFileWriter::DoScheduledWrite() { DCHECK(serializer_); - std::string data; - if (serializer_->SerializeData(&data)) { - WriteNow(data); + scoped_ptr<std::string> data(new std::string); + if (serializer_->SerializeData(data.get())) { + WriteNow(data.Pass()); } else { DLOG(WARNING) << "failed to serialize data to be saved in " << path_.value().c_str(); @@ -189,7 +196,7 @@ void ImportantFileWriter::RegisterOnNextSuccessfulWriteCallback( on_next_successful_write_ = on_next_successful_write; } -bool ImportantFileWriter::PostWriteTask(const std::string& data) { +bool ImportantFileWriter::PostWriteTask(const Callback<bool()>& task) { // TODO(gab): This code could always use PostTaskAndReplyWithResult and let // ForwardSuccessfulWrite() no-op if |on_next_successful_write_| is null, but // PostTaskAndReply causes memory leaks in tests (crbug.com/371974) and @@ -199,16 +206,13 @@ bool ImportantFileWriter::PostWriteTask(const std::string& data) { return base::PostTaskAndReplyWithResult( task_runner_.get(), FROM_HERE, - MakeCriticalClosure( - Bind(&ImportantFileWriter::WriteFileAtomically, path_, data)), + MakeCriticalClosure(task), Bind(&ImportantFileWriter::ForwardSuccessfulWrite, weak_factory_.GetWeakPtr())); } return task_runner_->PostTask( FROM_HERE, - MakeCriticalClosure( - Bind(IgnoreResult(&ImportantFileWriter::WriteFileAtomically), - path_, data))); + MakeCriticalClosure(base::Bind(IgnoreResult(task)))); } void ImportantFileWriter::ForwardSuccessfulWrite(bool result) { diff --git a/base/files/important_file_writer.h b/base/files/important_file_writer.h index 9ead9c1..99f1a7c 100644 --- a/base/files/important_file_writer.h +++ b/base/files/important_file_writer.h @@ -78,7 +78,7 @@ class BASE_EXPORT ImportantFileWriter : public NonThreadSafe { // Save |data| to target filename. Does not block. If there is a pending write // scheduled by ScheduleWrite, it is cancelled. - void WriteNow(const std::string& data); + void WriteNow(scoped_ptr<std::string> data); // Schedule a save to target filename. Data will be serialized and saved // to disk after the commit interval. If another ScheduleWrite is issued @@ -106,7 +106,7 @@ class BASE_EXPORT ImportantFileWriter : public NonThreadSafe { private: // Helper method for WriteNow(). - bool PostWriteTask(const std::string& data); + bool PostWriteTask(const Callback<bool()>& task); // If |result| is true and |on_next_successful_write_| is set, invokes // |on_successful_write_| and then resets it; no-ops otherwise. diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc index 98eaee8..170c2b2 100644 --- a/base/files/important_file_writer_unittest.cc +++ b/base/files/important_file_writer_unittest.cc @@ -100,7 +100,7 @@ TEST_F(ImportantFileWriterTest, Basic) { ImportantFileWriter writer(file_, MessageLoopProxy::current().get()); EXPECT_FALSE(PathExists(writer.path())); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); - writer.WriteNow("foo"); + writer.WriteNow(make_scoped_ptr(new std::string("foo"))); RunLoop().RunUntilIdle(); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); @@ -113,7 +113,7 @@ TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { EXPECT_FALSE(PathExists(writer.path())); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); successful_write_observer_.ObserveNextSuccessfulWrite(&writer); - writer.WriteNow("foo"); + writer.WriteNow(make_scoped_ptr(new std::string("foo"))); RunLoop().RunUntilIdle(); // Confirm that the observer is invoked. @@ -124,7 +124,7 @@ TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { // Confirm that re-installing the observer works for another write. EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); successful_write_observer_.ObserveNextSuccessfulWrite(&writer); - writer.WriteNow("bar"); + writer.WriteNow(make_scoped_ptr(new std::string("bar"))); RunLoop().RunUntilIdle(); EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); @@ -134,7 +134,7 @@ TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { // Confirm that writing again without re-installing the observer doesn't // result in a notification. EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); - writer.WriteNow("baz"); + writer.WriteNow(make_scoped_ptr(new std::string("baz"))); RunLoop().RunUntilIdle(); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index daafdbe..2612f9c 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc @@ -205,10 +205,10 @@ bool BookmarkStorage::SaveNow() { return false; } - std::string data; - if (!SerializeData(&data)) + scoped_ptr<std::string> data(new std::string); + if (!SerializeData(data.get())) return false; - writer_.WriteNow(data); + writer_.WriteNow(data.Pass()); return true; } |