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

Side by Side Diff: net/disk_cache/simple/simple_entry_impl.cc

Issue 2874833005: SimpleCache: read small files all at once. (Closed)
Patch Set: Add some metrics and an experiment knob. Not really happy with coverage, though. Created 3 years, 5 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 "net/disk_cache/simple/simple_entry_impl.h" 5 #include "net/disk_cache/simple/simple_entry_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <limits> 9 #include <limits>
10 #include <utility> 10 #include <utility>
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 const uint64_t entry_hash, 167 const uint64_t entry_hash,
168 OperationsMode operations_mode, 168 OperationsMode operations_mode,
169 SimpleBackendImpl* backend, 169 SimpleBackendImpl* backend,
170 net::NetLog* net_log) 170 net::NetLog* net_log)
171 : backend_(backend->AsWeakPtr()), 171 : backend_(backend->AsWeakPtr()),
172 cache_type_(cache_type), 172 cache_type_(cache_type),
173 worker_pool_(backend->worker_pool()), 173 worker_pool_(backend->worker_pool()),
174 path_(path), 174 path_(path),
175 entry_hash_(entry_hash), 175 entry_hash_(entry_hash),
176 use_optimistic_operations_(operations_mode == OPTIMISTIC_OPERATIONS), 176 use_optimistic_operations_(operations_mode == OPTIMISTIC_OPERATIONS),
177 first_stream1_read_(true),
177 last_used_(Time::Now()), 178 last_used_(Time::Now()),
178 last_modified_(last_used_), 179 last_modified_(last_used_),
179 sparse_data_size_(0), 180 sparse_data_size_(0),
180 open_count_(0), 181 open_count_(0),
181 doomed_(false), 182 doomed_(false),
182 state_(STATE_UNINITIALIZED), 183 state_(STATE_UNINITIALIZED),
183 synchronous_entry_(NULL), 184 synchronous_entry_(NULL),
184 net_log_( 185 net_log_(
185 net::NetLogWithSource::Make(net_log, 186 net::NetLogWithSource::Make(net_log,
186 net::NetLogSourceType::DISK_CACHE_ENTRY)), 187 net::NetLogSourceType::DISK_CACHE_ENTRY)),
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly. 539 // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly.
539 return net::OK; 540 return net::OK;
540 } 541 }
541 542
542 size_t SimpleEntryImpl::EstimateMemoryUsage() const { 543 size_t SimpleEntryImpl::EstimateMemoryUsage() const {
543 // TODO(xunjieli): crbug.com/669108. It'd be nice to have the rest of |entry| 544 // TODO(xunjieli): crbug.com/669108. It'd be nice to have the rest of |entry|
544 // measured, but the ownership of SimpleSynchronousEntry isn't straightforward 545 // measured, but the ownership of SimpleSynchronousEntry isn't straightforward
545 return sizeof(SimpleSynchronousEntry) + 546 return sizeof(SimpleSynchronousEntry) +
546 base::trace_event::EstimateMemoryUsage(pending_operations_) + 547 base::trace_event::EstimateMemoryUsage(pending_operations_) +
547 base::trace_event::EstimateMemoryUsage(executing_operation_) + 548 base::trace_event::EstimateMemoryUsage(executing_operation_) +
548 (stream_0_data_ ? stream_0_data_->capacity() : 0); 549 (stream_0_data_ ? stream_0_data_->capacity() : 0) +
550 (stream_1_prefetch_data_ ? stream_1_prefetch_data_->capacity() : 0);
549 } 551 }
550 552
551 SimpleEntryImpl::~SimpleEntryImpl() { 553 SimpleEntryImpl::~SimpleEntryImpl() {
552 DCHECK(io_thread_checker_.CalledOnValidThread()); 554 DCHECK(io_thread_checker_.CalledOnValidThread());
553 DCHECK_EQ(0U, pending_operations_.size()); 555 DCHECK_EQ(0U, pending_operations_.size());
554 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_FAILURE); 556 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_FAILURE);
555 DCHECK(!synchronous_entry_); 557 DCHECK(!synchronous_entry_);
556 net_log_.EndEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY); 558 net_log_.EndEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY);
557 } 559 }
558 560
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 if (!callback.is_null()) 841 if (!callback.is_null())
840 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 842 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
841 base::Bind(callback, 0)); 843 base::Bind(callback, 0));
842 return; 844 return;
843 } 845 }
844 846
845 buf_len = std::min(buf_len, GetDataSize(stream_index) - offset); 847 buf_len = std::min(buf_len, GetDataSize(stream_index) - offset);
846 848
847 // Since stream 0 data is kept in memory, it is read immediately. 849 // Since stream 0 data is kept in memory, it is read immediately.
848 if (stream_index == 0) { 850 if (stream_index == 0) {
849 int ret_value = ReadStream0Data(buf, offset, buf_len); 851 ReadInMemoryStreamData(stream_0_data_.get(), offset, buf_len, buf,
850 if (!callback.is_null()) { 852 callback);
851 base::ThreadTaskRunnerHandle::Get()->PostTask( 853 return;
852 FROM_HERE, base::Bind(callback, ret_value)); 854 }
855
856 // Sometimes we can read in-ram prefetched stream 1 data immediately, too.
857 if (stream_index == 1) {
858 if (first_stream1_read_) {
859 SIMPLE_CACHE_UMA(BOOLEAN, "ReadStream1FromPrefetched", cache_type_,
860 stream_1_prefetch_data_ != nullptr);
853 } 861 }
854 return; 862 first_stream1_read_ = false;
863
864 if (stream_1_prefetch_data_) {
865 ReadInMemoryStreamData(stream_1_prefetch_data_.get(), offset, buf_len,
866 buf, callback);
867 return;
868 }
855 } 869 }
856 870
857 state_ = STATE_IO_PENDING; 871 state_ = STATE_IO_PENDING;
858 if (!doomed_ && backend_.get()) 872 if (!doomed_ && backend_.get())
859 backend_->index()->UseIfExists(entry_hash_); 873 backend_->index()->UseIfExists(entry_hash_);
860 874
861 // Figure out if we should be computing the checksum for this read, 875 // Figure out if we should be computing the checksum for this read,
862 // and whether we should be verifying it, too. 876 // and whether we should be verifying it, too.
863 std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_request; 877 std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_request;
864 if (crc32s_end_offset_[stream_index] == offset) { 878 if (crc32s_end_offset_[stream_index] == offset) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 952 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
939 base::Bind(callback, 0)); 953 base::Bind(callback, 0));
940 } 954 }
941 return; 955 return;
942 } 956 }
943 } 957 }
944 state_ = STATE_IO_PENDING; 958 state_ = STATE_IO_PENDING;
945 if (!doomed_ && backend_.get()) 959 if (!doomed_ && backend_.get())
946 backend_->index()->UseIfExists(entry_hash_); 960 backend_->index()->UseIfExists(entry_hash_);
947 961
962 // Any stream 1 write invalidates the prefetched data.
963 if (stream_index == 1)
964 stream_1_prefetch_data_ = nullptr;
965
948 AdvanceCrc(buf, offset, buf_len, stream_index); 966 AdvanceCrc(buf, offset, buf_len, stream_index);
949 967
950 // |entry_stat| needs to be initialized before modifying |data_size_|. 968 // |entry_stat| needs to be initialized before modifying |data_size_|.
951 std::unique_ptr<SimpleEntryStat> entry_stat(new SimpleEntryStat( 969 std::unique_ptr<SimpleEntryStat> entry_stat(new SimpleEntryStat(
952 last_used_, last_modified_, data_size_, sparse_data_size_)); 970 last_used_, last_modified_, data_size_, sparse_data_size_));
953 if (truncate) { 971 if (truncate) {
954 data_size_[stream_index] = offset + buf_len; 972 data_size_[stream_index] = offset + buf_len;
955 } else { 973 } else {
956 data_size_[stream_index] = std::max(offset + buf_len, 974 data_size_[stream_index] = std::max(offset + buf_len,
957 GetDataSize(stream_index)); 975 GetDataSize(stream_index));
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 1160
1143 state_ = STATE_READY; 1161 state_ = STATE_READY;
1144 synchronous_entry_ = in_results->sync_entry; 1162 synchronous_entry_ = in_results->sync_entry;
1145 if (in_results->stream_0_data.get()) { 1163 if (in_results->stream_0_data.get()) {
1146 stream_0_data_ = in_results->stream_0_data; 1164 stream_0_data_ = in_results->stream_0_data;
1147 // The crc was read in SimpleSynchronousEntry. 1165 // The crc was read in SimpleSynchronousEntry.
1148 crc_check_state_[0] = CRC_CHECK_DONE; 1166 crc_check_state_[0] = CRC_CHECK_DONE;
1149 crc32s_[0] = in_results->stream_0_crc32; 1167 crc32s_[0] = in_results->stream_0_crc32;
1150 crc32s_end_offset_[0] = in_results->entry_stat.data_size(0); 1168 crc32s_end_offset_[0] = in_results->entry_stat.data_size(0);
1151 } 1169 }
1170
1171 if (in_results->stream_1_data.get()) {
1172 stream_1_prefetch_data_ = in_results->stream_1_data;
1173 // The crc was read in SimpleSynchronousEntry.
1174 crc_check_state_[1] = CRC_CHECK_DONE;
1175 crc32s_[1] = in_results->stream_1_crc32;
1176 crc32s_end_offset_[1] = in_results->entry_stat.data_size(1);
1177 }
1178
1152 // If this entry was opened by hash, key_ could still be empty. If so, update 1179 // If this entry was opened by hash, key_ could still be empty. If so, update
1153 // it with the key read from the synchronous entry. 1180 // it with the key read from the synchronous entry.
1154 if (key_.empty()) { 1181 if (key_.empty()) {
1155 SetKey(synchronous_entry_->key()); 1182 SetKey(synchronous_entry_->key());
1156 } else { 1183 } else {
1157 // This should only be triggered when creating an entry. In the open case 1184 // This should only be triggered when creating an entry. In the open case
1158 // the key is either copied from the arguments to open, or checked 1185 // the key is either copied from the arguments to open, or checked
1159 // in the synchronous entry. 1186 // in the synchronous entry.
1160 DCHECK_EQ(key_, synchronous_entry_->key()); 1187 DCHECK_EQ(key_, synchronous_entry_->key());
1161 } 1188 }
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 } else { 1464 } else {
1438 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE 1465 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
1439 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; 1466 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
1440 } 1467 }
1441 } 1468 }
1442 SIMPLE_CACHE_UMA(ENUMERATION, 1469 SIMPLE_CACHE_UMA(ENUMERATION,
1443 "WriteDependencyType", cache_type_, 1470 "WriteDependencyType", cache_type_,
1444 type, WRITE_DEPENDENCY_TYPE_MAX); 1471 type, WRITE_DEPENDENCY_TYPE_MAX);
1445 } 1472 }
1446 1473
1447 int SimpleEntryImpl::ReadStream0Data(net::IOBuffer* buf, 1474 void SimpleEntryImpl::ReadInMemoryStreamData(
1448 int offset, 1475 net::GrowableIOBuffer* in_buf,
1449 int buf_len) { 1476 int offset,
1477 int buf_len,
1478 net::IOBuffer* out_buf,
1479 const CompletionCallback& callback) {
1480 int rv;
1450 if (buf_len < 0) { 1481 if (buf_len < 0) {
1451 RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE); 1482 RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE);
1452 return 0; 1483 rv = 0;
1484 } else {
1485 memcpy(out_buf->data(), in_buf->data() + offset, buf_len);
1486 UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_,
1487 data_size_, sparse_data_size_));
1488 RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
1489 rv = buf_len;
1453 } 1490 }
1454 memcpy(buf->data(), stream_0_data_->data() + offset, buf_len); 1491 if (!callback.is_null()) {
1455 UpdateDataFromEntryStat( 1492 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1456 SimpleEntryStat(base::Time::Now(), last_modified_, data_size_, 1493 base::Bind(callback, rv));
1457 sparse_data_size_)); 1494 }
1458 RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
1459 return buf_len;
1460 } 1495 }
1461 1496
1462 int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf, 1497 int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf,
1463 int offset, 1498 int offset,
1464 int buf_len, 1499 int buf_len,
1465 bool truncate) { 1500 bool truncate) {
1466 // Currently, stream 0 is only used for HTTP headers, and always writes them 1501 // Currently, stream 0 is only used for HTTP headers, and always writes them
1467 // with a single, truncating write. Detect these writes and record the size 1502 // with a single, truncating write. Detect these writes and record the size
1468 // changes of the headers. Also, support writes to stream 0 that have 1503 // changes of the headers. Also, support writes to stream 0 that have
1469 // different access patterns, as required by the API contract. 1504 // different access patterns, as required by the API contract.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 } 1551 }
1517 crc32s_end_offset_[stream_index] = offset + length; 1552 crc32s_end_offset_[stream_index] = offset + length;
1518 } else if (offset < crc32s_end_offset_[stream_index]) { 1553 } else if (offset < crc32s_end_offset_[stream_index]) {
1519 // If a range for which the crc32 was already computed is rewritten, the 1554 // If a range for which the crc32 was already computed is rewritten, the
1520 // computation of the crc32 need to start from 0 again. 1555 // computation of the crc32 need to start from 0 again.
1521 crc32s_end_offset_[stream_index] = 0; 1556 crc32s_end_offset_[stream_index] = 0;
1522 } 1557 }
1523 } 1558 }
1524 1559
1525 } // namespace disk_cache 1560 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698