Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <utility> | 5 #include <utility> |
| 6 | 6 |
| 7 #include "media/blink/multibuffer.h" | 7 #include "media/blink/multibuffer.h" |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/message_loop/message_loop.h" | |
| 10 | 11 |
| 11 namespace media { | 12 namespace media { |
| 12 | 13 |
| 14 // Prune 80 blocks per 30 seconds. | |
| 15 // This means a full cache will go away in ~5 minutes. | |
| 16 enum { | |
| 17 kBlockPruneInterval = 30, | |
| 18 kBlocksPrunedPerInterval = 80, | |
| 19 }; | |
| 20 | |
| 13 // Returns the block ID closest to (but less or equal than) |pos| from |index|. | 21 // Returns the block ID closest to (but less or equal than) |pos| from |index|. |
| 14 template <class T> | 22 template <class T> |
| 15 static MultiBuffer::BlockId ClosestPreviousEntry( | 23 static MultiBuffer::BlockId ClosestPreviousEntry( |
| 16 const std::map<MultiBuffer::BlockId, T>& index, | 24 const std::map<MultiBuffer::BlockId, T>& index, |
| 17 MultiBuffer::BlockId pos) { | 25 MultiBuffer::BlockId pos) { |
| 18 auto i = index.upper_bound(pos); | 26 auto i = index.upper_bound(pos); |
| 19 DCHECK(i == index.end() || i->first > pos); | 27 DCHECK(i == index.end() || i->first > pos); |
| 20 if (i == index.begin()) { | 28 if (i == index.begin()) { |
| 21 return std::numeric_limits<MultiBufferBlockId>::min(); | 29 return std::numeric_limits<MultiBufferBlockId>::min(); |
| 22 } | 30 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 35 if (i == index.end()) { | 43 if (i == index.end()) { |
| 36 return std::numeric_limits<MultiBufferBlockId>::max(); | 44 return std::numeric_limits<MultiBufferBlockId>::max(); |
| 37 } | 45 } |
| 38 DCHECK_GE(i->first, pos); | 46 DCHECK_GE(i->first, pos); |
| 39 return i->first; | 47 return i->first; |
| 40 } | 48 } |
| 41 | 49 |
| 42 // | 50 // |
| 43 // MultiBuffer::GlobalLRU | 51 // MultiBuffer::GlobalLRU |
| 44 // | 52 // |
| 45 MultiBuffer::GlobalLRU::GlobalLRU() : max_size_(0), data_size_(0) {} | 53 MultiBuffer::GlobalLRU::GlobalLRU() |
| 54 : max_size_(0), data_size_(0), background_pruning_active_(false) {} | |
| 46 | 55 |
| 47 MultiBuffer::GlobalLRU::~GlobalLRU() { | 56 MultiBuffer::GlobalLRU::~GlobalLRU() { |
| 48 // By the time we're freed, all blocks should have been removed, | 57 // By the time we're freed, all blocks should have been removed, |
| 49 // and our sums should be zero. | 58 // and our sums should be zero. |
| 50 DCHECK(lru_.Empty()); | 59 DCHECK(lru_.Empty()); |
| 51 DCHECK_EQ(max_size_, 0); | 60 DCHECK_EQ(max_size_, 0); |
| 52 DCHECK_EQ(data_size_, 0); | 61 DCHECK_EQ(data_size_, 0); |
| 53 } | 62 } |
| 54 | 63 |
| 55 void MultiBuffer::GlobalLRU::Use(MultiBuffer* multibuffer, | 64 void MultiBuffer::GlobalLRU::Use(MultiBuffer* multibuffer, |
| 56 MultiBufferBlockId block_id) { | 65 MultiBufferBlockId block_id) { |
| 57 GlobalBlockId id(multibuffer, block_id); | 66 GlobalBlockId id(multibuffer, block_id); |
| 58 lru_.Use(id); | 67 lru_.Use(id); |
| 68 SchedulePrune(); | |
| 59 } | 69 } |
| 60 | 70 |
| 61 void MultiBuffer::GlobalLRU::Insert(MultiBuffer* multibuffer, | 71 void MultiBuffer::GlobalLRU::Insert(MultiBuffer* multibuffer, |
| 62 MultiBufferBlockId block_id) { | 72 MultiBufferBlockId block_id) { |
| 63 GlobalBlockId id(multibuffer, block_id); | 73 GlobalBlockId id(multibuffer, block_id); |
| 64 lru_.Insert(id); | 74 lru_.Insert(id); |
| 75 SchedulePrune(); | |
| 65 } | 76 } |
| 66 | 77 |
| 67 void MultiBuffer::GlobalLRU::Remove(MultiBuffer* multibuffer, | 78 void MultiBuffer::GlobalLRU::Remove(MultiBuffer* multibuffer, |
| 68 MultiBufferBlockId block_id) { | 79 MultiBufferBlockId block_id) { |
| 69 GlobalBlockId id(multibuffer, block_id); | 80 GlobalBlockId id(multibuffer, block_id); |
| 70 lru_.Remove(id); | 81 lru_.Remove(id); |
| 71 } | 82 } |
| 72 | 83 |
| 73 bool MultiBuffer::GlobalLRU::Contains(MultiBuffer* multibuffer, | 84 bool MultiBuffer::GlobalLRU::Contains(MultiBuffer* multibuffer, |
| 74 MultiBufferBlockId block_id) { | 85 MultiBufferBlockId block_id) { |
| 75 GlobalBlockId id(multibuffer, block_id); | 86 GlobalBlockId id(multibuffer, block_id); |
| 76 return lru_.Contains(id); | 87 return lru_.Contains(id); |
| 77 } | 88 } |
| 78 | 89 |
| 79 void MultiBuffer::GlobalLRU::IncrementDataSize(int64_t blocks) { | 90 void MultiBuffer::GlobalLRU::IncrementDataSize(int64_t blocks) { |
| 80 data_size_ += blocks; | 91 data_size_ += blocks; |
| 81 DCHECK_GE(data_size_, 0); | 92 DCHECK_GE(data_size_, 0); |
| 82 } | 93 } |
| 83 | 94 |
| 84 void MultiBuffer::GlobalLRU::IncrementMaxSize(int64_t blocks) { | 95 void MultiBuffer::GlobalLRU::IncrementMaxSize(int64_t blocks) { |
| 85 max_size_ += blocks; | 96 max_size_ += blocks; |
| 86 DCHECK_GE(max_size_, 0); | 97 DCHECK_GE(max_size_, 0); |
| 98 SchedulePrune(); | |
| 99 } | |
| 100 | |
| 101 bool MultiBuffer::GlobalLRU::Pruneable() const { | |
| 102 return data_size_ > max_size_ && !lru_.Empty(); | |
| 103 } | |
| 104 | |
| 105 void MultiBuffer::GlobalLRU::SchedulePrune() { | |
| 106 if (Pruneable() && !background_pruning_active_) { | |
| 107 base::MessageLoop::current()->PostDelayedTask( | |
| 108 FROM_HERE, base::Bind(&MultiBuffer::GlobalLRU::PruneTask, this), | |
| 109 base::TimeDelta::FromSeconds(kBlockPruneInterval)); | |
| 110 background_pruning_active_ = true; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void MultiBuffer::GlobalLRU::PruneTask() { | |
| 115 background_pruning_active_ = false; | |
|
DaleCurtis
2016/03/24 19:12:24
This disables pruning on the first scheduled one a
hubbe
2016/03/24 20:57:40
I renamed background_pruning_active_ to backround_
| |
| 116 Prune(kBlocksPrunedPerInterval); | |
| 117 SchedulePrune(); | |
| 87 } | 118 } |
| 88 | 119 |
| 89 void MultiBuffer::GlobalLRU::Prune(int64_t max_to_free) { | 120 void MultiBuffer::GlobalLRU::Prune(int64_t max_to_free) { |
| 90 // We group the blocks by multibuffer so that we can free as many blocks as | 121 // We group the blocks by multibuffer so that we can free as many blocks as |
| 91 // possible in one call. This reduces the number of callbacks to clients | 122 // possible in one call. This reduces the number of callbacks to clients |
| 92 // when their available ranges change. | 123 // when their available ranges change. |
| 93 std::map<MultiBuffer*, std::vector<MultiBufferBlockId>> to_free; | 124 std::map<MultiBuffer*, std::vector<MultiBufferBlockId>> to_free; |
| 94 int64_t freed = 0; | 125 int64_t freed = 0; |
| 95 while (data_size_ - freed > max_size_ && !lru_.Empty() && | 126 while (data_size_ - freed > max_size_ && !lru_.Empty() && |
| 96 freed < max_to_free) { | 127 freed < max_to_free) { |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 } | 507 } |
| 477 | 508 |
| 478 void MultiBuffer::IncrementMaxSize(int32_t size) { | 509 void MultiBuffer::IncrementMaxSize(int32_t size) { |
| 479 max_size_ += size; | 510 max_size_ += size; |
| 480 lru_->IncrementMaxSize(size); | 511 lru_->IncrementMaxSize(size); |
| 481 DCHECK_GE(max_size_, 0); | 512 DCHECK_GE(max_size_, 0); |
| 482 // Pruning only happens when blocks are added. | 513 // Pruning only happens when blocks are added. |
| 483 } | 514 } |
| 484 | 515 |
| 485 } // namespace media | 516 } // namespace media |
| OLD | NEW |