Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: content/browser/indexed_db/leveldb/leveldb_database.cc

Issue 2760163002: [IndexedDB] Pool and evict leveldb iterators, to save memory (Closed)
Patch Set: compile fixed Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
6 6
7 #include <inttypes.h> 7 #include <inttypes.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <cerrno> 10 #include <cerrno>
(...skipping 23 matching lines...) Expand all
34 #include "third_party/leveldatabase/env_chromium.h" 34 #include "third_party/leveldatabase/env_chromium.h"
35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
36 #include "third_party/leveldatabase/src/include/leveldb/db.h" 36 #include "third_party/leveldatabase/src/include/leveldb/db.h"
37 #include "third_party/leveldatabase/src/include/leveldb/env.h" 37 #include "third_party/leveldatabase/src/include/leveldb/env.h"
38 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h" 38 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
39 #include "third_party/leveldatabase/src/include/leveldb/slice.h" 39 #include "third_party/leveldatabase/src/include/leveldb/slice.h"
40 40
41 using base::StringPiece; 41 using base::StringPiece;
42 42
43 namespace content { 43 namespace content {
44 static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50;
jsbell 2017/03/22 23:55:32 We should note that this applies only to iterators
dmurph 2017/03/23 20:56:48 Done.
44 45
45 // Forcing flushes to disk at the end of a transaction guarantees that the 46 // Forcing flushes to disk at the end of a transaction guarantees that the
46 // data hit disk, but drastically impacts throughput when the filesystem is 47 // data hit disk, but drastically impacts throughput when the filesystem is
47 // busy with background compactions. Not syncing trades off reliability for 48 // busy with background compactions. Not syncing trades off reliability for
48 // performance. Note that background compactions which move data from the 49 // performance. Note that background compactions which move data from the
49 // log to SSTs are always done with reliable writes. 50 // log to SSTs are always done with reliable writes.
50 // 51 //
51 // Sync writes are necessary on Windows for quota calculations; POSIX 52 // Sync writes are necessary on Windows for quota calculations; POSIX
52 // calculates file sizes correctly even when not synced to disk. 53 // calculates file sizes correctly even when not synced to disk.
53 #if defined(OS_WIN) 54 #if defined(OS_WIN)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 const leveldb::Slice& limit) const {} 86 const leveldb::Slice& limit) const {}
86 87
87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( 88 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor(
88 std::string* key) const {} 89 std::string* key) const {}
89 90
90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) 91 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} 92 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
92 93
93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } 94 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); }
94 95
95 LevelDBDatabase::LevelDBDatabase() {} 96 LevelDBDatabase::LevelDBDatabase()
97 : iterator_lru_(kDefaultMaxOpenIteratorsPerDatabase) {}
98
99 LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators)
100 : iterator_lru_(max_open_iterators) {}
96 101
97 LevelDBDatabase::~LevelDBDatabase() { 102 LevelDBDatabase::~LevelDBDatabase() {
103 LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators",
104 max_iterators_);
98 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( 105 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
99 this); 106 this);
100 // db_'s destructor uses comparator_adapter_; order of deletion is important. 107 // db_'s destructor uses comparator_adapter_; order of deletion is important.
101 CloseDatabase(); 108 CloseDatabase();
102 comparator_adapter_.reset(); 109 comparator_adapter_.reset();
103 env_.reset(); 110 env_.reset();
104 } 111 }
105 112
106 void LevelDBDatabase::CloseDatabase() { 113 void LevelDBDatabase::CloseDatabase() {
107 if (db_) { 114 if (db_) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 LEVEL_DB_MAX_ERROR, 285 LEVEL_DB_MAX_ERROR,
279 LEVEL_DB_MAX_ERROR + 1, 286 LEVEL_DB_MAX_ERROR + 1,
280 base::HistogramBase::kUmaTargetedHistogramFlag) 287 base::HistogramBase::kUmaTargetedHistogramFlag)
281 ->Add(leveldb_error); 288 ->Add(leveldb_error);
282 if (s.IsIOError()) 289 if (s.IsIOError())
283 ParseAndHistogramIOErrorDetails(histogram_name, s); 290 ParseAndHistogramIOErrorDetails(histogram_name, s);
284 else 291 else
285 ParseAndHistogramCorruptionDetails(histogram_name, s); 292 ParseAndHistogramCorruptionDetails(histogram_name, s);
286 } 293 }
287 294
295 leveldb::Status LevelDBDatabase::OpenForTesting(
jsbell 2017/03/22 23:55:32 Too much duplicated code. :( Can we refactor? I d
dmurph 2017/03/23 20:56:48 Done.
296 const base::FilePath& file_name,
297 const LevelDBComparator* comparator,
298 std::unique_ptr<LevelDBDatabase>* result,
299 size_t max_open_cursors) {
300 IDB_TRACE("LevelDBDatabase::Open");
301 base::TimeTicks begin_time = base::TimeTicks::Now();
302
303 std::unique_ptr<ComparatorAdapter> comparator_adapter(
304 base::MakeUnique<ComparatorAdapter>(comparator));
305
306 std::unique_ptr<leveldb::DB> db;
307 std::unique_ptr<const leveldb::FilterPolicy> filter_policy;
308 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(),
309 file_name, &db, &filter_policy);
310
311 if (!s.ok()) {
312 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s);
313 LOG(ERROR) << "Failed to open LevelDB database from "
314 << file_name.AsUTF8Unsafe() << "," << s.ToString();
315 return s;
316 }
317
318 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime",
319 base::TimeTicks::Now() - begin_time);
320
321 CheckFreeSpace("Success", file_name);
322
323 (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors));
324 (*result)->db_ = std::move(db);
325 (*result)->comparator_adapter_ = std::move(comparator_adapter);
326 (*result)->comparator_ = comparator;
327 (*result)->filter_policy_ = std::move(filter_policy);
328 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe();
329 return s;
330 }
331
288 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, 332 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
289 const LevelDBComparator* comparator, 333 const LevelDBComparator* comparator,
290 std::unique_ptr<LevelDBDatabase>* result, 334 std::unique_ptr<LevelDBDatabase>* result,
291 bool* is_disk_full) { 335 bool* is_disk_full) {
292 IDB_TRACE("LevelDBDatabase::Open"); 336 IDB_TRACE("LevelDBDatabase::Open");
293 base::TimeTicks begin_time = base::TimeTicks::Now(); 337 base::TimeTicks begin_time = base::TimeTicks::Now();
294 338
295 std::unique_ptr<ComparatorAdapter> comparator_adapter( 339 std::unique_ptr<ComparatorAdapter> comparator_adapter(
296 base::MakeUnique<ComparatorAdapter>(comparator)); 340 base::MakeUnique<ComparatorAdapter>(comparator));
297 341
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); 516 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
473 dump->AddString("file_name", "", file_name_for_tracing); 517 dump->AddString("file_name", "", file_name_for_tracing);
474 518
475 // Memory is allocated from system allocator (malloc). 519 // Memory is allocated from system allocator (malloc).
476 pmd->AddSuballocation(dump->guid(), 520 pmd->AddSuballocation(dump->guid(),
477 base::trace_event::MemoryDumpManager::GetInstance() 521 base::trace_event::MemoryDumpManager::GetInstance()
478 ->system_allocator_pool_name()); 522 ->system_allocator_pool_name());
479 return true; 523 return true;
480 } 524 }
481 525
526 void LevelDBDatabase::NotifyIteratorCreated(LevelDBIterator* iter) {
527 num_iterators_++;
528 max_iterators_ = std::max(max_iterators_, num_iterators_);
529 }
530
531 void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) {
532 // This line updates the LRU if the item exists.
533 if (iterator_lru_.Get(iter) != iterator_lru_.end())
534 return;
535 if (iterator_lru_.size() == iterator_lru_.max_size()) {
536 auto to_evict_iter = iterator_lru_.rbegin();
537 LevelDBIterator* to_evict = to_evict_iter->first;
538 to_evict->PurgeMemory();
539 iterator_lru_.Erase(to_evict_iter);
540 }
541 iterator_lru_.Put(iter, iter);
542 }
543
544 void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) {
545 DCHECK_GT(num_iterators_, 0u);
546 --num_iterators_;
547 auto it = iterator_lru_.Get(iter);
jsbell 2017/03/22 23:55:32 Peek() instead of Get(), since we don't need to me
dmurph 2017/03/23 20:56:47 Done.
548 if (it == iterator_lru_.end())
549 return;
550 iterator_lru_.Erase(it);
551 }
482 } // namespace content 552 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698