Disk: ReadDriver: Add unified cache

Previously, we had to copy an entire block out of the
old cache every time we wanted to read even a single
byte from it.

This ended up being a fairly significant performance
issue, in addition to the fact that the caching code
was duplicated.
This commit is contained in:
Paul Hollinsky
2022-04-14 18:26:44 -04:00
parent d45d708446
commit 103f938d69
10 changed files with 316 additions and 245 deletions
+52
View File
@@ -61,4 +61,56 @@ TEST_F(DiskDriverTest, ReadBadStartingPos) {
const auto amountRead = readLogicalDisk(2000, buf.data(), buf.size());
EXPECT_FALSE(amountRead.has_value());
EXPECT_EQ(driver->readCalls, 1u); // One to check EOF
}
TEST_F(DiskDriverTest, ReadCache) {
std::array<uint8_t, 128> buf;
buf.fill(0u);
auto amountRead = readLogicalDisk(1, buf.data(), buf.size());
EXPECT_TRUE(amountRead.has_value());
EXPECT_EQ(amountRead, buf.size());
EXPECT_EQ(buf[0], TEST_STRING[1]);
EXPECT_EQ(buf[110], 111u);
EXPECT_EQ(driver->readCalls, 1u);
// Subsequent reads (within the same second) should hit the cache
amountRead = readLogicalDisk(1, buf.data(), buf.size());
EXPECT_EQ(driver->readCalls, 1u);
// The underlying data can be changed
driver->mockDisk[1] = 'J';
// But the same data should be returned from the cache
amountRead = readLogicalDisk(1, buf.data(), buf.size());
EXPECT_TRUE(amountRead.has_value());
EXPECT_EQ(amountRead, buf.size());
EXPECT_EQ(buf[0], TEST_STRING[1]);
EXPECT_EQ(buf[110], 111u);
EXPECT_EQ(driver->readCalls, 1u);
driver->invalidateCache(0, 0xfffff);
// After invalidating the cache (or waiting for it to expire), the underlying data will be read
amountRead = readLogicalDisk(1, buf.data(), buf.size());
EXPECT_TRUE(amountRead.has_value());
EXPECT_EQ(amountRead, buf.size());
EXPECT_EQ(buf[0], 'J');
EXPECT_EQ(buf[110], 111u);
EXPECT_EQ(driver->readCalls, 2u);
}
TEST_F(DiskDriverTest, ReadCacheLong) {
std::array<uint8_t, 500> buf;
buf.fill(0u);
auto amountRead = readLogicalDisk(300, buf.data(), buf.size());
EXPECT_TRUE(amountRead.has_value());
EXPECT_EQ(amountRead, buf.size());
EXPECT_EQ(buf[0], 300 & 0xFF);
EXPECT_EQ(buf[110], 410 & 0xFF);
EXPECT_EQ(driver->readCalls, 3u);
// Re-read the end, it will be in the cache
amountRead = readLogicalDisk(780, buf.data() + 480, buf.size() - 480);
EXPECT_EQ(buf[490], 790 & 0xFF);
EXPECT_EQ(driver->readCalls, 3u);
}