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 |