Commit d99ef40d authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[code caching] Handle small data with a single read/write

- Many small reads and writes are observed, especially with the JavaScript
  code cache. Detect these and write all data into the entry's stream 0,
  and clear stream 1. When reading, detect the entry size and for small
  data, skip the stream 1 read and copy the data from the stream 0 read.
- Changes the stream 0 data (again) to a header with response time and
  data size. The data size, while not strictly necessary right now, will
  be needed if we implement de-duplication of identical entries stored by
  multiple origins. We can add the code hash to this header, and the size
  field will disambiguate between small entries and large de-duplicated
  entries where we use the hash as a key to the data.
- This change should make small reads faster than before, as synchronous
  completion of stream 0 reads is observed. Otherwise, there should be no
  change in performance.
- Renames the buffers and completion callbacks to reflect small/large data
  distinction.

Bug: chromium:992991
Change-Id: I6fb5337ef1e4148dd9f300f0a8c85acb401be62e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1834562
Commit-Queue: Bill Budge <bbudge@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMythri Alle <mythria@chromium.org>
Reviewed-by: default avatarMaks Orlovich <morlovich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702667}
parent 4529d179
...@@ -122,7 +122,7 @@ class CONTENT_EXPORT GeneratedCodeCache { ...@@ -122,7 +122,7 @@ class CONTENT_EXPORT GeneratedCodeCache {
enum Operation { kFetch, kWrite, kDelete, kGetBackend }; enum Operation { kFetch, kWrite, kDelete, kGetBackend };
// Data streams corresponding to each entry. // Data streams corresponding to each entry.
enum { kResponseTimeStream = 0, kDataStream = 1 }; enum { kSmallDataStream = 0, kLargeDataStream = 1 };
// Creates a simple_disk_cache backend. // Creates a simple_disk_cache backend.
void CreateBackend(); void CreateBackend();
...@@ -138,15 +138,15 @@ class CONTENT_EXPORT GeneratedCodeCache { ...@@ -138,15 +138,15 @@ class CONTENT_EXPORT GeneratedCodeCache {
void WriteEntryImpl(PendingOperation* op); void WriteEntryImpl(PendingOperation* op);
void OpenCompleteForWrite(PendingOperation* op, void OpenCompleteForWrite(PendingOperation* op,
disk_cache::EntryResult result); disk_cache::EntryResult result);
void WriteResponseTimeComplete(PendingOperation* op, int rv); void WriteSmallBufferComplete(PendingOperation* op, int rv);
void WriteDataComplete(PendingOperation* op, int rv); void WriteLargeBufferComplete(PendingOperation* op, int rv);
// Fetches entry from cache. // Fetches entry from cache.
void FetchEntryImpl(PendingOperation* op); void FetchEntryImpl(PendingOperation* op);
void OpenCompleteForRead(PendingOperation* op, void OpenCompleteForRead(PendingOperation* op,
disk_cache::EntryResult result); disk_cache::EntryResult result);
void ReadResponseTimeComplete(PendingOperation* op, int rv); void ReadSmallBufferComplete(PendingOperation* op, int rv);
void ReadDataComplete(PendingOperation* op, int rv); void ReadLargeBufferComplete(PendingOperation* op, int rv);
// Deletes entry from cache. // Deletes entry from cache.
void DeleteEntryImpl(PendingOperation* op); void DeleteEntryImpl(PendingOperation* op);
......
...@@ -17,6 +17,7 @@ namespace content { ...@@ -17,6 +17,7 @@ namespace content {
class GeneratedCodeCacheTest : public testing::Test { class GeneratedCodeCacheTest : public testing::Test {
public: public:
static const int kLargeSizeInBytes = 8192;
static const int kMaxSizeInBytes = 1024 * 1024; static const int kMaxSizeInBytes = 1024 * 1024;
static constexpr char kInitialUrl[] = "http://example.com/script.js"; static constexpr char kInitialUrl[] = "http://example.com/script.js";
static constexpr char kInitialOrigin[] = "http://example.com"; static constexpr char kInitialOrigin[] = "http://example.com";
...@@ -153,6 +154,23 @@ TEST_F(GeneratedCodeCacheTest, WriteEntry) { ...@@ -153,6 +154,23 @@ TEST_F(GeneratedCodeCacheTest, WriteEntry) {
EXPECT_EQ(response_time, received_response_time_); EXPECT_EQ(response_time, received_response_time_);
} }
TEST_F(GeneratedCodeCacheTest, WriteLargeEntry) {
GURL new_url("http://example1.com/script.js");
GURL origin_lock = GURL(kInitialOrigin);
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string large_data(kLargeSizeInBytes, 'x');
base::Time response_time = base::Time::Now();
WriteToCache(new_url, origin_lock, large_data, response_time);
task_environment_.RunUntilIdle();
FetchFromCache(new_url, origin_lock);
task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(large_data, received_data_);
EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, DeleteEntry) { TEST_F(GeneratedCodeCacheTest, DeleteEntry) {
GURL url(kInitialUrl); GURL url(kInitialUrl);
GURL origin_lock = GURL(kInitialOrigin); GURL origin_lock = GURL(kInitialOrigin);
...@@ -229,6 +247,23 @@ TEST_F(GeneratedCodeCacheTest, WriteEntryPendingOp) { ...@@ -229,6 +247,23 @@ TEST_F(GeneratedCodeCacheTest, WriteEntryPendingOp) {
EXPECT_EQ(response_time, received_response_time_); EXPECT_EQ(response_time, received_response_time_);
} }
TEST_F(GeneratedCodeCacheTest, WriteLargeEntryPendingOp) {
GURL new_url("http://example1.com/script1.js");
GURL origin_lock = GURL(kInitialOrigin);
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string large_data(kLargeSizeInBytes, 'x');
base::Time response_time = base::Time::Now();
WriteToCache(new_url, origin_lock, large_data, response_time);
task_environment_.RunUntilIdle();
FetchFromCache(new_url, origin_lock);
task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(large_data, received_data_);
EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, DeleteEntryPendingOp) { TEST_F(GeneratedCodeCacheTest, DeleteEntryPendingOp) {
GURL url(kInitialUrl); GURL url(kInitialUrl);
GURL origin_lock = GURL(kInitialOrigin); GURL origin_lock = GURL(kInitialOrigin);
...@@ -259,6 +294,63 @@ TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) { ...@@ -259,6 +294,63 @@ TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) {
EXPECT_EQ(response_time, received_response_time_); EXPECT_EQ(response_time, received_response_time_);
} }
TEST_F(GeneratedCodeCacheTest, UpdateDataOfSmallExistingEntry) {
GURL url(kInitialUrl);
GURL origin_lock = GURL(kInitialOrigin);
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string new_data(kLargeSizeInBytes, 'x');
base::Time response_time = base::Time::Now();
WriteToCache(url, origin_lock, new_data, response_time);
task_environment_.RunUntilIdle();
FetchFromCache(url, origin_lock);
task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(new_data, received_data_);
EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, UpdateDataOfLargeExistingEntry) {
GURL url(kInitialUrl);
GURL origin_lock = GURL(kInitialOrigin);
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string large_data(kLargeSizeInBytes, 'x');
base::Time response_time = base::Time::Now();
WriteToCache(url, origin_lock, large_data, response_time);
std::string new_data = large_data + "Overwrite";
response_time = base::Time::Now();
WriteToCache(url, origin_lock, new_data, response_time);
task_environment_.RunUntilIdle();
FetchFromCache(url, origin_lock);
task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(new_data, received_data_);
EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, TruncateDataOfLargeExistingEntry) {
GURL url(kInitialUrl);
GURL origin_lock = GURL(kInitialOrigin);
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string large_data(kLargeSizeInBytes, 'x');
base::Time response_time = base::Time::Now();
WriteToCache(url, origin_lock, large_data, response_time);
std::string new_data = "SerializedCodeForScriptOverwrite";
response_time = base::Time::Now();
WriteToCache(url, origin_lock, new_data, response_time);
task_environment_.RunUntilIdle();
FetchFromCache(url, origin_lock);
task_environment_.RunUntilIdle();
ASSERT_TRUE(received_);
EXPECT_EQ(new_data, received_data_);
EXPECT_EQ(response_time, received_response_time_);
}
TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) { TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) {
InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
GURL new_origin_lock = GURL("http://not-example.com"); GURL new_origin_lock = GURL("http://not-example.com");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment