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

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 : iterator_lru_(max_open_iterators) {
97 DCHECK(max_open_iterators);
98 }
96 99
97 LevelDBDatabase::~LevelDBDatabase() { 100 LevelDBDatabase::~LevelDBDatabase() {
101 LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators",
102 max_iterators_);
98 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( 103 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
99 this); 104 this);
100 // db_'s destructor uses comparator_adapter_; order of deletion is important. 105 // db_'s destructor uses comparator_adapter_; order of deletion is important.
101 CloseDatabase(); 106 CloseDatabase();
102 comparator_adapter_.reset(); 107 comparator_adapter_.reset();
103 env_.reset(); 108 env_.reset();
104 } 109 }
105 110
106 void LevelDBDatabase::CloseDatabase() { 111 void LevelDBDatabase::CloseDatabase() {
107 if (db_) { 112 if (db_) {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 base::HistogramBase::kUmaTargetedHistogramFlag) 285 base::HistogramBase::kUmaTargetedHistogramFlag)
281 ->Add(leveldb_error); 286 ->Add(leveldb_error);
282 if (s.IsIOError()) 287 if (s.IsIOError())
283 ParseAndHistogramIOErrorDetails(histogram_name, s); 288 ParseAndHistogramIOErrorDetails(histogram_name, s);
284 else 289 else
285 ParseAndHistogramCorruptionDetails(histogram_name, s); 290 ParseAndHistogramCorruptionDetails(histogram_name, s);
286 } 291 }
287 292
288 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, 293 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
289 const LevelDBComparator* comparator, 294 const LevelDBComparator* comparator,
295 size_t max_open_cursors,
290 std::unique_ptr<LevelDBDatabase>* result, 296 std::unique_ptr<LevelDBDatabase>* result,
291 bool* is_disk_full) { 297 bool* is_disk_full) {
292 IDB_TRACE("LevelDBDatabase::Open"); 298 IDB_TRACE("LevelDBDatabase::Open");
293 base::TimeTicks begin_time = base::TimeTicks::Now(); 299 base::TimeTicks begin_time = base::TimeTicks::Now();
294 300
295 std::unique_ptr<ComparatorAdapter> comparator_adapter( 301 std::unique_ptr<ComparatorAdapter> comparator_adapter(
296 base::MakeUnique<ComparatorAdapter>(comparator)); 302 base::MakeUnique<ComparatorAdapter>(comparator));
297 303
298 std::unique_ptr<leveldb::DB> db; 304 std::unique_ptr<leveldb::DB> db;
299 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; 305 std::unique_ptr<const leveldb::FilterPolicy> filter_policy;
(...skipping 11 matching lines...) Expand all
311 LOG(ERROR) << "Failed to open LevelDB database from " 317 LOG(ERROR) << "Failed to open LevelDB database from "
312 << file_name.AsUTF8Unsafe() << "," << s.ToString(); 318 << file_name.AsUTF8Unsafe() << "," << s.ToString();
313 return s; 319 return s;
314 } 320 }
315 321
316 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", 322 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime",
317 base::TimeTicks::Now() - begin_time); 323 base::TimeTicks::Now() - begin_time);
318 324
319 CheckFreeSpace("Success", file_name); 325 CheckFreeSpace("Success", file_name);
320 326
321 (*result) = base::WrapUnique(new LevelDBDatabase()); 327 (*result) = base::WrapUnique(new LevelDBDatabase(max_open_cursors));
322 (*result)->db_ = std::move(db); 328 (*result)->db_ = std::move(db);
323 (*result)->comparator_adapter_ = std::move(comparator_adapter); 329 (*result)->comparator_adapter_ = std::move(comparator_adapter);
324 (*result)->comparator_ = comparator; 330 (*result)->comparator_ = comparator;
325 (*result)->filter_policy_ = std::move(filter_policy); 331 (*result)->filter_policy_ = std::move(filter_policy);
326 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe(); 332 (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe();
327 333
328 return s; 334 return s;
329 } 335 }
330 336
331 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( 337 std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
332 const LevelDBComparator* comparator) { 338 const LevelDBComparator* comparator) {
333 std::unique_ptr<ComparatorAdapter> comparator_adapter( 339 std::unique_ptr<ComparatorAdapter> comparator_adapter(
334 base::MakeUnique<ComparatorAdapter>(comparator)); 340 base::MakeUnique<ComparatorAdapter>(comparator));
335 std::unique_ptr<leveldb::Env> in_memory_env( 341 std::unique_ptr<leveldb::Env> in_memory_env(
336 leveldb::NewMemEnv(LevelDBEnv::Get())); 342 leveldb::NewMemEnv(LevelDBEnv::Get()));
337 343
338 std::unique_ptr<leveldb::DB> db; 344 std::unique_ptr<leveldb::DB> db;
339 std::unique_ptr<const leveldb::FilterPolicy> filter_policy; 345 std::unique_ptr<const leveldb::FilterPolicy> filter_policy;
340 const leveldb::Status s = OpenDB(comparator_adapter.get(), 346 const leveldb::Status s = OpenDB(comparator_adapter.get(),
341 in_memory_env.get(), 347 in_memory_env.get(),
342 base::FilePath(), 348 base::FilePath(),
343 &db, 349 &db,
344 &filter_policy); 350 &filter_policy);
345 351
346 if (!s.ok()) { 352 if (!s.ok()) {
347 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString(); 353 LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString();
348 return std::unique_ptr<LevelDBDatabase>(); 354 return std::unique_ptr<LevelDBDatabase>();
349 } 355 }
350 356
351 std::unique_ptr<LevelDBDatabase> result = 357 std::unique_ptr<LevelDBDatabase> result = base::WrapUnique(
352 base::WrapUnique(new LevelDBDatabase()); 358 new LevelDBDatabase(kDefaultMaxOpenIteratorsPerDatabase));
353 result->env_ = std::move(in_memory_env); 359 result->env_ = std::move(in_memory_env);
354 result->db_ = std::move(db); 360 result->db_ = std::move(db);
355 result->comparator_adapter_ = std::move(comparator_adapter); 361 result->comparator_adapter_ = std::move(comparator_adapter);
356 result->comparator_ = comparator; 362 result->comparator_ = comparator;
357 result->filter_policy_ = std::move(filter_policy); 363 result->filter_policy_ = std::move(filter_policy);
358 result->file_name_for_tracing = "in-memory-database"; 364 result->file_name_for_tracing = "in-memory-database";
359 365
360 return result; 366 return result;
361 } 367 }
362 368
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 return s; 432 return s;
427 } 433 }
428 434
429 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( 435 std::unique_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator(
430 const LevelDBSnapshot* snapshot) { 436 const LevelDBSnapshot* snapshot) {
431 leveldb::ReadOptions read_options; 437 leveldb::ReadOptions read_options;
432 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the 438 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the
433 // performance impact is too great. 439 // performance impact is too great.
434 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; 440 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0;
435 441
442 num_iterators_++;
443 max_iterators_ = std::max(max_iterators_, num_iterators_);
444 // Iterator isn't added to lru cache until it is used, as memory isn't loaded
445 // for the iterator until it's first Seek call.
436 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); 446 std::unique_ptr<leveldb::Iterator> i(db_->NewIterator(read_options));
437 return std::unique_ptr<LevelDBIterator>( 447 return std::unique_ptr<LevelDBIterator>(
438 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i))); 448 IndexedDBClassFactory::Get()->CreateIteratorImpl(std::move(i), this,
449 read_options.snapshot));
439 } 450 }
440 451
441 const LevelDBComparator* LevelDBDatabase::Comparator() const { 452 const LevelDBComparator* LevelDBDatabase::Comparator() const {
442 return comparator_; 453 return comparator_;
443 } 454 }
444 455
445 void LevelDBDatabase::Compact(const base::StringPiece& start, 456 void LevelDBDatabase::Compact(const base::StringPiece& start,
446 const base::StringPiece& stop) { 457 const base::StringPiece& stop) {
447 IDB_TRACE("LevelDBDatabase::Compact"); 458 IDB_TRACE("LevelDBDatabase::Compact");
448 const leveldb::Slice start_slice = MakeSlice(start); 459 const leveldb::Slice start_slice = MakeSlice(start);
(...skipping 23 matching lines...) Expand all
472 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); 483 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
473 dump->AddString("file_name", "", file_name_for_tracing); 484 dump->AddString("file_name", "", file_name_for_tracing);
474 485
475 // Memory is allocated from system allocator (malloc). 486 // Memory is allocated from system allocator (malloc).
476 pmd->AddSuballocation(dump->guid(), 487 pmd->AddSuballocation(dump->guid(),
477 base::trace_event::MemoryDumpManager::GetInstance() 488 base::trace_event::MemoryDumpManager::GetInstance()
478 ->system_allocator_pool_name()); 489 ->system_allocator_pool_name());
479 return true; 490 return true;
480 } 491 }
481 492
493 std::unique_ptr<leveldb::Iterator> LevelDBDatabase::CreateLevelDBIterator(
494 const leveldb::Snapshot* snapshot) {
495 leveldb::ReadOptions read_options;
496 read_options.verify_checksums = true;
497 read_options.snapshot = snapshot;
498 return std::unique_ptr<leveldb::Iterator>(db_->NewIterator(read_options));
499 }
500
501 LevelDBDatabase::DetachIteratorOnDestruct::~DetachIteratorOnDestruct() {
502 if (it_)
503 it_->Detach();
504 }
505
506 void LevelDBDatabase::OnIteratorUsed(LevelDBIterator* iter) {
507 // This line updates the LRU if the item exists.
508 if (iterator_lru_.Get(iter) != iterator_lru_.end())
509 return;
510 DetachIteratorOnDestruct purger(iter);
511 iterator_lru_.Put(iter, std::move(purger));
512 }
513
514 void LevelDBDatabase::OnIteratorDestroyed(LevelDBIterator* iter) {
515 DCHECK_GT(num_iterators_, 0u);
516 --num_iterators_;
517 auto it = iterator_lru_.Peek(iter);
518 if (it == iterator_lru_.end())
519 return;
520 iterator_lru_.Erase(it);
521 }
522
482 } // namespace content 523 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/leveldb/leveldb_database.h ('k') | content/browser/indexed_db/leveldb/leveldb_iterator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698