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

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: comments 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 const leveldb::Slice& limit) const {} 85 const leveldb::Slice& limit) const {}
86 86
87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( 87 void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor(
88 std::string* key) const {} 88 std::string* key) const {}
89 89
90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) 90 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} 91 : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
92 92
93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } 93 LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); }
94 94
95 LevelDBDatabase::LevelDBDatabase() {} 95 LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators)
96 : eviction_enabled_(max_open_iterators != NO_CURSOR_EVICTION),
97 iterator_lru_(max_open_iterators) {}
96 98
97 LevelDBDatabase::~LevelDBDatabase() { 99 LevelDBDatabase::~LevelDBDatabase() {
100 LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators",
101 max_iterators_);
98 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( 102 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
99 this); 103 this);
100 // db_'s destructor uses comparator_adapter_; order of deletion is important. 104 // db_'s destructor uses comparator_adapter_; order of deletion is important.
101 CloseDatabase(); 105 CloseDatabase();
102 comparator_adapter_.reset(); 106 comparator_adapter_.reset();
103 env_.reset(); 107 env_.reset();
104 } 108 }
105 109
106 void LevelDBDatabase::CloseDatabase() { 110 void LevelDBDatabase::CloseDatabase() {
107 if (db_) { 111 if (db_) {
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 ->Add(leveldb_error); 285 ->Add(leveldb_error);
282 if (s.IsIOError()) 286 if (s.IsIOError())
283 ParseAndHistogramIOErrorDetails(histogram_name, s); 287 ParseAndHistogramIOErrorDetails(histogram_name, s);
284 else 288 else
285 ParseAndHistogramCorruptionDetails(histogram_name, s); 289 ParseAndHistogramCorruptionDetails(histogram_name, s);
286 } 290 }
287 291
288 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, 292 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
289 const LevelDBComparator* comparator, 293 const LevelDBComparator* comparator,
290 std::unique_ptr<LevelDBDatabase>* result, 294 std::unique_ptr<LevelDBDatabase>* result,
295 size_t max_open_cursors,
291 bool* is_disk_full) { 296 bool* is_disk_full) {
292 IDB_TRACE("LevelDBDatabase::Open"); 297 IDB_TRACE("LevelDBDatabase::Open");
293 base::TimeTicks begin_time = base::TimeTicks::Now(); 298 base::TimeTicks begin_time = base::TimeTicks::Now();
294 299
295 std::unique_ptr<ComparatorAdapter> comparator_adapter( 300 std::unique_ptr<ComparatorAdapter> comparator_adapter(
296 base::MakeUnique<ComparatorAdapter>(comparator)); 301 base::MakeUnique<ComparatorAdapter>(comparator));
297 302
298 std::unique_ptr<leveldb::DB> db; 303 std::unique_ptr<leveldb::DB> db;
299 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; 304 std::unique_ptr<const leveldb::FilterPolicy> filter_policy;
300 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(), 305 const leveldb::Status s = OpenDB(comparator_adapter.get(), LevelDBEnv::Get(),
(...skipping 10 matching lines...) Expand all
311 LOG(ERROR) << "Failed to open LevelDB database from " 316 LOG(ERROR) << "Failed to open LevelDB database from "
312 << file_name.AsUTF8Unsafe() << "," << s.ToString(); 317 << file_name.AsUTF8Unsafe() << "," << s.ToString();
313 return s; 318 return s;
314 } 319 }
315 320
316 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", 321 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime",
317 base::TimeTicks::Now() - begin_time); 322 base::TimeTicks::Now() - begin_time);
318 323
319 CheckFreeSpace("Success", file_name); 324 CheckFreeSpace("Success", file_name);
320 325
321 (*result) = base::WrapUnique(new LevelDBDatabase()); 326 (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors));
322 (*result)->db_ = std::move(db); 327 (*result)->db_ = std::move(db);
323 (*result)->comparator_adapter_ = std::move(comparator_adapter); 328 (*result)->comparator_adapter_ = std::move(comparator_adapter);
324 (*result)->comparator_ = comparator; 329 (*result)->comparator_ = comparator;
325 (*result)->filter_policy_ = std::move(filter_policy); 330 (*result)->filter_policy_ = std::move(filter_policy);
326 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); 331 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe();
327 332
328 return s; 333 return s;
329 } 334 }
330 335
331 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( 336 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
(...skipping 10 matching lines...) Expand all
342 base::FilePath(), 347 base::FilePath(),
343 &db, 348 &db,
344 &filter_policy); 349 &filter_policy);
345 350
346 if (!s.ok()) { 351 if (!s.ok()) {
347 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString(); 352 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString();
348 return std::unique_ptr<LevelDBDatabase>(); 353 return std::unique_ptr<LevelDBDatabase>();
349 } 354 }
350 355
351 std::unique_ptr<LevelDBDatabase> result = 356 std::unique_ptr<LevelDBDatabase> result =
352 base::WrapUnique(new LevelDBDatabase()); 357 base::WrapUnique(new LevelDBDatabase(NO_CURSOR_EVICTION));
jsbell 2017/03/23 21:48:21 Interesting... I suppose we should check Incognito
dmurph 2017/03/23 22:48:46 Well - cursor pooling would do nothing. Everything
353 result->env_ = std::move(in_memory_env); 358 result->env_ = std::move(in_memory_env);
354 result->db_ = std::move(db); 359 result->db_ = std::move(db);
355 result->comparator_adapter_ = std::move(comparator_adapter); 360 result->comparator_adapter_ = std::move(comparator_adapter);
356 result->comparator_ = comparator; 361 result->comparator_ = comparator;
357 result->filter_policy_ = std::move(filter_policy); 362 result->filter_policy_ = std::move(filter_policy);
358 result->file_name_for_tracing = "in-memory-database"; 363 result->file_name_for_tracing = "in-memory-database";
359 364
360 return result; 365 return result;
361 } 366 }
362 367
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 return s; 431 return s;
427 } 432 }
428 433
429 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( 434 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator(
430 const LevelDBSnapshot* snapshot) { 435 const LevelDBSnapshot* snapshot) {
431 leveldb::ReadOptions read_options; 436 leveldb::ReadOptions read_options;
432 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the 437 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the
433 // performance impact is too great. 438 // performance impact is too great.
434 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; 439 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0;
435 440
441 num_iterators_++;
442 max_iterators_ = std::max(max_iterators_, num_iterators_);
436 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); 443 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options));
437 return std::unique_ptr<LevelDBIterator>( 444 return std::unique_ptr<LevelDBIterator>(
438 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i))); 445 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i), this,
446 read_options.snapshot));
439 } 447 }
440 448
441 const LevelDBComparator* LevelDBDatabase::Comparator() const { 449 const LevelDBComparator* LevelDBDatabase::Comparator() const {
442 return comparator_; 450 return comparator_;
443 } 451 }
444 452
445 void LevelDBDatabase::Compact(const base::StringPiece& start, 453 void LevelDBDatabase::Compact(const base::StringPiece& start,
446 const base::StringPiece& stop) { 454 const base::StringPiece& stop) {
447 IDB_TRACE("LevelDBDatabase::Compact"); 455 IDB_TRACE("LevelDBDatabase::Compact");
448 const leveldb::Slice start_slice = MakeSlice(start); 456 const leveldb::Slice start_slice = MakeSlice(start);
(...skipping 23 matching lines...) Expand all
472 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); 480 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
473 dump->AddString("file_name", "", file_name_for_tracing); 481 dump->AddString("file_name", "", file_name_for_tracing);
474 482
475 // Memory is allocated from system allocator (malloc). 483 // Memory is allocated from system allocator (malloc).
476 pmd->AddSuballocation(dump->guid(), 484 pmd->AddSuballocation(dump->guid(),
477 base::trace_event::MemoryDumpManager::GetInstance() 485 base::trace_event::MemoryDumpManager::GetInstance()
478 ->system_allocator_pool_name()); 486 ->system_allocator_pool_name());
479 return true; 487 return true;
480 } 488 }
481 489
490 std::unique_ptr<leveldb::Iterator> LevelDBDatabase::CreateLevelDBIterator(
491 const leveldb::Snapshot* snapshot) {
492 leveldb::ReadOptions read_options;
493 read_options.verify_checksums = true;
494 read_options.snapshot = snapshot;
495 return std::unique_ptr<leveldb::Iterator>(db_->NewIterator(read_options));
496 }
497
498 void LevelDBDatabase::NotifyIteratorUsed(LevelDBIterator* iter) {
499 // This line updates the LRU if the item exists.
500 if (!eviction_enabled_ || iterator_lru_.Get(iter) != iterator_lru_.end())
501 return;
502 if (iterator_lru_.size() == iterator_lru_.max_size()) {
503 auto to_evict_iter = iterator_lru_.rbegin();
504 LevelDBIterator* to_evict = to_evict_iter->first;
505 to_evict->PurgeMemory();
506 iterator_lru_.Erase(to_evict_iter);
507 }
508 iterator_lru_.Put(iter, iter);
509 }
510
511 void LevelDBDatabase::NotifyIteratorDestroyed(LevelDBIterator* iter) {
512 DCHECK_GT(num_iterators_, 0u);
513 --num_iterators_;
514 if (!eviction_enabled_)
515 return;
516 auto it = iterator_lru_.Peek(iter);
517 if (it == iterator_lru_.end())
518 return;
519 iterator_lru_.Erase(it);
520 }
482 } // namespace content 521 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698