Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "storage/browser/blob/blob_memory_controller.h" | 5 #include "storage/browser/blob/blob_memory_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <numeric> | 8 #include <numeric> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/containers/small_map.h" | 12 #include "base/containers/small_map.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/guid.h" | 14 #include "base/guid.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
| 17 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 18 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 19 #include "base/numerics/safe_math.h" | 19 #include "base/numerics/safe_math.h" |
| 20 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
| 21 #include "base/stl_util.h" | 21 #include "base/stl_util.h" |
| 22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/sys_info.h" | |
| 23 #include "base/task_runner.h" | 24 #include "base/task_runner.h" |
| 24 #include "base/task_runner_util.h" | 25 #include "base/task_runner_util.h" |
| 25 #include "base/threading/thread_restrictions.h" | 26 #include "base/threading/thread_restrictions.h" |
| 26 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 27 #include "base/trace_event/trace_event.h" | 28 #include "base/trace_event/trace_event.h" |
| 28 #include "base/tuple.h" | |
| 29 #include "storage/browser/blob/blob_data_builder.h" | 29 #include "storage/browser/blob/blob_data_builder.h" |
| 30 #include "storage/browser/blob/blob_data_item.h" | 30 #include "storage/browser/blob/blob_data_item.h" |
| 31 #include "storage/browser/blob/shareable_blob_data_item.h" | 31 #include "storage/browser/blob/shareable_blob_data_item.h" |
| 32 #include "storage/browser/blob/shareable_file_reference.h" | 32 #include "storage/browser/blob/shareable_file_reference.h" |
| 33 #include "storage/common/data_element.h" | 33 #include "storage/common/data_element.h" |
| 34 | 34 |
| 35 using base::File; | 35 using base::File; |
| 36 using base::FilePath; | 36 using base::FilePath; |
| 37 | 37 |
| 38 namespace storage { | 38 namespace storage { |
| 39 namespace { | 39 namespace { |
| 40 | |
| 40 using FileCreationInfo = BlobMemoryController::FileCreationInfo; | 41 using FileCreationInfo = BlobMemoryController::FileCreationInfo; |
| 41 using MemoryAllocation = BlobMemoryController::MemoryAllocation; | 42 using MemoryAllocation = BlobMemoryController::MemoryAllocation; |
| 42 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask; | 43 using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask; |
| 43 | 44 |
| 45 // CrOS: | |
| 46 // * Ram - 20% | |
|
jsbell
2016/12/07 00:01:24
Nit: Capitalize RAM or just say 'Memory'
| |
| 47 // * Disk - 50% | |
| 48 // Android: | |
| 49 // * RAM - 20% | |
| 50 // * Disk - 5% | |
| 51 // Desktop: | |
| 52 // * Ram - 20%, or 2 gigs if x64. | |
|
jsbell
2016/12/07 00:01:24
Nit: GB or GiB
| |
| 53 // * Disk - 10% | |
|
michaeln
2016/12/06 21:58:23
hmmm... i'm not sure how to evaluate these numbers
dmurph
2016/12/06 22:12:43
Josh, Victor, and I chatted for a while about them
michaeln
2016/12/06 23:11:25
I'm not sure, i haven't thought much about the pol
dmurph
2016/12/06 23:20:50
Free disk space changes, so I didn't want to use t
| |
| 54 BlobStorageLimits CalculateBlobStorageLimitsImpl(const FilePath& storage_dir, | |
| 55 bool disk_enabled) { | |
| 56 BlobStorageLimits output; | |
| 57 | |
| 58 int64_t disk_size = | |
| 59 disk_enabled ? base::SysInfo::AmountOfTotalDiskSpace(storage_dir) : 0ull; | |
| 60 int64_t memory_size = base::SysInfo::AmountOfPhysicalMemory(); | |
| 61 | |
| 62 BlobStorageLimits limits; | |
| 63 | |
| 64 if (memory_size > 0) { | |
| 65 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS) | |
|
michaeln
2016/12/06 23:11:25
is there such a thing as a 64bit system with < 2G
dmurph
2016/12/06 23:20:50
The reasoning here is that if it's x64, then it ha
| |
| 66 static const size_t kTwoGigabytes = 2ull * 1024 * 1024 * 1024; | |
| 67 limits.max_blob_in_memory_space = kTwoGigabytes; | |
| 68 #else | |
| 69 limits.max_blob_in_memory_space = static_cast<size_t>(memory_size / 5ll); | |
| 70 #endif | |
| 71 } | |
| 72 | |
| 73 if (disk_size > 0) { | |
| 74 #if defined(OS_CHROMEOS) | |
| 75 limits.max_blob_disk_space = static_cast<size_t>(disk_size / 2ll); | |
| 76 #elif defined(OS_ANDROID) | |
| 77 limits.max_blob_disk_space = static_cast<size_t>(disk_size / 20ll); | |
| 78 #else | |
| 79 limits.max_blob_disk_space = static_cast<size_t>(disk_size / 10ll); | |
| 80 #endif | |
| 81 } | |
| 82 return limits; | |
| 83 } | |
| 84 | |
| 44 File::Error CreateBlobDirectory(const FilePath& blob_storage_dir) { | 85 File::Error CreateBlobDirectory(const FilePath& blob_storage_dir) { |
| 45 File::Error error = File::FILE_OK; | 86 File::Error error = File::FILE_OK; |
| 46 base::CreateDirectoryAndGetError(blob_storage_dir, &error); | 87 base::CreateDirectoryAndGetError(blob_storage_dir, &error); |
| 47 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.CreateDirectoryResult", -error, | 88 UMA_HISTOGRAM_ENUMERATION("Storage.Blob.CreateDirectoryResult", -error, |
| 48 -File::FILE_ERROR_MAX); | 89 -File::FILE_ERROR_MAX); |
| 49 DLOG_IF(ERROR, error != File::FILE_OK) | 90 DLOG_IF(ERROR, error != File::FILE_OK) |
| 50 << "Error creating blob storage directory: " << error; | 91 << "Error creating blob storage directory: " << error; |
| 51 return error; | 92 return error; |
| 52 } | 93 } |
| 53 | 94 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 return Strategy::TOO_LARGE; | 455 return Strategy::TOO_LARGE; |
| 415 | 456 |
| 416 // Handle the case where we have all the bytes preemptively transported, and | 457 // Handle the case where we have all the bytes preemptively transported, and |
| 417 // we can also fit them. | 458 // we can also fit them. |
| 418 if (preemptive_transported_bytes == total_transportation_bytes && | 459 if (preemptive_transported_bytes == total_transportation_bytes && |
| 419 pending_memory_quota_tasks_.empty() && | 460 pending_memory_quota_tasks_.empty() && |
| 420 preemptive_transported_bytes < GetAvailableMemoryForBlobs()) { | 461 preemptive_transported_bytes < GetAvailableMemoryForBlobs()) { |
| 421 return Strategy::NONE_NEEDED; | 462 return Strategy::NONE_NEEDED; |
| 422 } | 463 } |
| 423 if (file_paging_enabled_ && | 464 if (file_paging_enabled_ && |
| 424 (total_transportation_bytes > limits_.memory_limit_before_paging())) { | 465 total_transportation_bytes <= GetAvailableFileSpaceForBlobs() && |
| 466 total_transportation_bytes > limits_.memory_limit_before_paging()) { | |
| 425 return Strategy::FILE; | 467 return Strategy::FILE; |
| 426 } | 468 } |
| 427 if (total_transportation_bytes > limits_.max_ipc_memory_size) | 469 if (total_transportation_bytes > limits_.max_ipc_memory_size) |
| 428 return Strategy::SHARED_MEMORY; | 470 return Strategy::SHARED_MEMORY; |
| 429 return Strategy::IPC; | 471 return Strategy::IPC; |
| 430 } | 472 } |
| 431 | 473 |
| 432 bool BlobMemoryController::CanReserveQuota(uint64_t size) const { | 474 bool BlobMemoryController::CanReserveQuota(uint64_t size) const { |
| 433 // We check each size independently as a blob can't be constructed in both | 475 // We check each size independently as a blob can't be constructed in both |
| 434 // disk and memory. | 476 // disk and memory. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 auto iterator = populated_memory_items_.Get(item->item_id()); | 551 auto iterator = populated_memory_items_.Get(item->item_id()); |
| 510 if (iterator == populated_memory_items_.end()) { | 552 if (iterator == populated_memory_items_.end()) { |
| 511 populated_memory_items_bytes_ += | 553 populated_memory_items_bytes_ += |
| 512 static_cast<size_t>(item->item()->length()); | 554 static_cast<size_t>(item->item()->length()); |
| 513 populated_memory_items_.Put(item->item_id(), item.get()); | 555 populated_memory_items_.Put(item->item_id(), item.get()); |
| 514 } | 556 } |
| 515 } | 557 } |
| 516 MaybeScheduleEvictionUntilSystemHealthy(); | 558 MaybeScheduleEvictionUntilSystemHealthy(); |
| 517 } | 559 } |
| 518 | 560 |
| 561 void BlobMemoryController::CalculateBlobStorageLimits() { | |
| 562 if (file_runner_) { | |
| 563 PostTaskAndReplyWithResult( | |
| 564 file_runner_.get(), FROM_HERE, | |
| 565 base::Bind(&CalculateBlobStorageLimitsImpl, blob_storage_dir_, true), | |
| 566 base::Bind(&BlobMemoryController::OnStorageLimitsCalculated, | |
| 567 weak_factory_.GetWeakPtr())); | |
| 568 } else { | |
| 569 OnStorageLimitsCalculated( | |
| 570 CalculateBlobStorageLimitsImpl(blob_storage_dir_, false)); | |
| 571 } | |
| 572 } | |
| 573 | |
| 574 base::WeakPtr<BlobMemoryController> BlobMemoryController::GetWeakPtr() { | |
| 575 return weak_factory_.GetWeakPtr(); | |
| 576 } | |
| 577 | |
| 578 void BlobMemoryController::OnStorageLimitsCalculated(BlobStorageLimits limits) { | |
| 579 if (!limits.IsValid() || manual_limits_set_) | |
| 580 return; | |
| 581 limits_ = limits; | |
| 582 } | |
| 583 | |
| 519 base::WeakPtr<QuotaAllocationTask> BlobMemoryController::AppendMemoryTask( | 584 base::WeakPtr<QuotaAllocationTask> BlobMemoryController::AppendMemoryTask( |
| 520 uint64_t total_bytes_needed, | 585 uint64_t total_bytes_needed, |
| 521 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items, | 586 std::vector<scoped_refptr<ShareableBlobDataItem>> unreserved_memory_items, |
| 522 const MemoryQuotaRequestCallback& done_callback) { | 587 const MemoryQuotaRequestCallback& done_callback) { |
| 523 DCHECK(file_paging_enabled_) | 588 DCHECK(file_paging_enabled_) |
| 524 << "Caller tried to reserve memory when CanReserveQuota(" | 589 << "Caller tried to reserve memory when CanReserveQuota(" |
| 525 << total_bytes_needed << ") would have returned false."; | 590 << total_bytes_needed << ") would have returned false."; |
| 526 | 591 |
| 527 pending_memory_quota_total_size_ += total_bytes_needed; | 592 pending_memory_quota_total_size_ += total_bytes_needed; |
| 528 pending_memory_quota_tasks_.push_back( | 593 pending_memory_quota_tasks_.push_back( |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 MaybeGrantPendingMemoryRequests(); | 806 MaybeGrantPendingMemoryRequests(); |
| 742 } | 807 } |
| 743 | 808 |
| 744 void BlobMemoryController::OnBlobFileDelete(uint64_t size, | 809 void BlobMemoryController::OnBlobFileDelete(uint64_t size, |
| 745 const FilePath& path) { | 810 const FilePath& path) { |
| 746 DCHECK_LE(size, disk_used_); | 811 DCHECK_LE(size, disk_used_); |
| 747 disk_used_ -= size; | 812 disk_used_ -= size; |
| 748 } | 813 } |
| 749 | 814 |
| 750 } // namespace storage | 815 } // namespace storage |
| OLD | NEW |