Changeset 179779 in webkit
- Timestamp:
- Feb 7, 2015, 11:18:30 AM (10 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r179774 r179779 1 2015-02-07 Antti Koivisto <antti@apple.com> 2 3 Use longer hashes for cache keys 4 https://bugs.webkit.org/show_bug.cgi?id=141356 5 6 Reviewed by Darin Adler. 7 8 The current key hashes are 32bit. We should use longer hashes to eliminate collisions. 9 10 This patch switches us to using MD5 digests for the cache key hashes. As a result the file names for the cache 11 entries grow from 8 to 32 character. 12 13 Note that we don't need a cryptographic hash (full cache keys are verified against the entries). 14 MD5 just happens to be fast, convenient and available. 15 16 The patch also moves the whole cache hierarchy down to a versioned subdirectory ("WebKitCache/Version 2") 17 and deletes any old style cache files if they exist. 18 19 * NetworkProcess/cache/NetworkCacheCoders.cpp: 20 (WebKit::NetworkCacheCoder<MD5::Digest>::encode): 21 (WebKit::NetworkCacheCoder<MD5::Digest>::decode): 22 * NetworkProcess/cache/NetworkCacheCoders.h: 23 * NetworkProcess/cache/NetworkCacheKey.cpp: 24 (WebKit::NetworkCacheKey::NetworkCacheKey): 25 (WebKit::hashString): 26 (WebKit::NetworkCacheKey::computeHash): 27 (WebKit::NetworkCacheKey::hashAsString): 28 (WebKit::NetworkCacheKey::stringToHash): 29 * NetworkProcess/cache/NetworkCacheKey.h: 30 (WebKit::NetworkCacheKey::shortHash): 31 (WebKit::NetworkCacheKey::toShortHash): 32 33 32bit hash to use in the bloom filter. 34 35 (WebKit::NetworkCacheKey::hashStringLength): 36 * NetworkProcess/cache/NetworkCacheStorage.h: 37 38 Bump the version. 39 40 * NetworkProcess/cache/NetworkCacheStorageCocoa.mm: 41 (WebKit::traverseCacheFiles): 42 (WebKit::makeVersionedDirectoryPath): 43 (WebKit::NetworkCacheStorage::NetworkCacheStorage): 44 (WebKit::NetworkCacheStorage::initialize): 45 (WebKit::NetworkCacheStorage::removeEntry): 46 (WebKit::NetworkCacheStorage::retrieve): 47 (WebKit::NetworkCacheStorage::store): 48 (WebKit::NetworkCacheStorage::update): 49 (WebKit::NetworkCacheStorage::shrinkIfNeeded): 50 (WebKit::NetworkCacheStorage::deleteOldVersions): 51 52 Wipe out the version 1 cache. 53 1 54 2015-02-06 Chris Dumez <cdumez@apple.com> 2 55 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
r179708 r179779 241 241 auto elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count(); 242 242 #endif 243 fprintf(stderr, "retireved %d\n", success); 243 244 LOG(NetworkCache, "(NetworkProcess) retrieve complete success=%d priority=%u time=%lldms", success, originalRequest.priority(), elapsedMS); 244 245 completionHandler(WTF::move(decodedEntry)); -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.cpp
r176400 r179779 1 1 /* 2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 174 174 } 175 175 176 void NetworkCacheCoder<MD5::Digest>::encode(NetworkCacheEncoder& encoder, const MD5::Digest& digest) 177 { 178 encoder.encodeFixedLengthData(digest.data(), sizeof(digest)); 179 } 180 181 bool NetworkCacheCoder<MD5::Digest>::decode(NetworkCacheDecoder& decoder, MD5::Digest& digest) 182 { 183 return decoder.decodeFixedLengthData(digest.data(), sizeof(digest)); 184 } 185 176 186 } 177 187 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.h
r176400 r179779 1 1 /* 2 * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2010, 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 37 37 #include <wtf/HashSet.h> 38 38 #include <wtf/Vector.h> 39 #include <wtf/md5.h> 39 40 40 41 namespace WebKit { … … 256 257 }; 257 258 259 template<> struct NetworkCacheCoder<MD5::Digest> { 260 static void encode(NetworkCacheEncoder&, const MD5::Digest&); 261 static bool decode(NetworkCacheDecoder&, MD5::Digest&); 262 }; 263 258 264 } 259 265 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp
r177294 r179779 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include "NetworkCacheCoders.h" 32 #include <wtf/ASCIICType.h> 33 #include <wtf/text/CString.h> 34 #include <wtf/text/StringBuilder.h> 32 35 33 36 namespace WebKit { … … 57 60 } 58 61 59 static NetworkCacheKey::HashType hashString(const String& string)62 static void hashString(MD5& md5, const String& string) 60 63 { 61 // String::hash() masks away the top bits. 62 if (string.is8Bit()) 63 return StringHasher::computeHash(string.characters8(), string.length()); 64 return StringHasher::computeHash(string.characters16(), string.length()); 64 const uint8_t zero = 0; 65 if (string.is8Bit()) { 66 md5.addBytes(string.characters8(), string.length()); 67 md5.addBytes(&zero, 1); 68 return; 69 } 70 auto cString = string.utf8(); 71 md5.addBytes(reinterpret_cast<const uint8_t*>(cString.data()), cString.length()); 72 md5.addBytes(&zero, 1); 65 73 } 66 74 67 75 NetworkCacheKey::HashType NetworkCacheKey::computeHash() const 68 76 { 69 return WTF::pairIntHash(hashString(m_method), WTF::pairIntHash(hashString(m_identifier), hashString(m_partition))); 77 // We don't really need a cryptographic hash. The key is always verified against the entry header. 78 // MD5 just happens to be suitably sized, fast and available. 79 MD5 md5; 80 hashString(md5, m_method); 81 hashString(md5, m_partition); 82 hashString(md5, m_identifier); 83 MD5::Digest hash; 84 md5.checksum(hash); 85 return hash; 70 86 } 71 87 72 88 String NetworkCacheKey::hashAsString() const 73 89 { 74 return String::format("%08x", m_hash); 90 StringBuilder builder; 91 for (auto byte : m_hash) { 92 builder.append(upperNibbleToASCIIHexDigit(byte)); 93 builder.append(lowerNibbleToASCIIHexDigit(byte)); 94 } 95 return builder.toString(); 96 } 97 98 template <typename CharType> bool hexDigitsToHash(CharType* characters, NetworkCacheKey::HashType& hash) 99 { 100 for (unsigned i = 0; i < sizeof(hash); ++i) { 101 auto high = characters[2 * i]; 102 auto low = characters[2 * i + 1]; 103 if (!isASCIIHexDigit(high) || !isASCIIHexDigit(low)) 104 return false; 105 hash[i] = toASCIIHexValue(high, low); 106 } 107 return true; 75 108 } 76 109 77 110 bool NetworkCacheKey::stringToHash(const String& string, HashType& hash) 78 111 { 79 if (string.length() != 8)112 if (string.length() != hashStringLength()) 80 113 return false; 81 bool success;82 hash = string.toUIntStrict(&success, 16);83 return success;114 if (string.is8Bit()) 115 return hexDigitsToHash(string.characters8(), hash); 116 return hexDigitsToHash(string.characters16(), hash); 84 117 } 85 118 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h
r177294 r179779 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(NETWORK_CACHE) 30 30 31 #include <wtf/md5.h> 31 32 #include <wtf/text/WTFString.h> 32 33 … … 38 39 class NetworkCacheKey { 39 40 public: 40 typedef unsignedHashType;41 typedef MD5::Digest HashType; 41 42 42 43 NetworkCacheKey() { } … … 48 49 const String& partition() const { return m_partition; } 49 50 const String& identifier() const { return m_identifier; } 51 50 52 HashType hash() const { return m_hash; } 53 unsigned shortHash() const { return toShortHash(m_hash); } 51 54 55 static unsigned toShortHash(const HashType& hash) { return *reinterpret_cast<const unsigned*>(hash.data()); } 56 static bool stringToHash(const String&, HashType&); 57 58 static size_t hashStringLength() { return 2 * sizeof(m_hash); } 52 59 String hashAsString() const; 53 static bool stringToHash(const String&, HashType&);54 60 55 61 void encode(NetworkCacheEncoder&) const; -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h
r179708 r179779 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 154 154 void clear(); 155 155 156 static const unsigned version = 1;156 static const unsigned version = 2; 157 157 158 158 private: … … 160 160 161 161 void initialize(); 162 void deleteOldVersions(); 162 163 void shrinkIfNeeded(); 163 164 … … 184 185 }; 185 186 187 const String m_baseDirectoryPath; 186 188 const String m_directoryPath; 187 189 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm
r179727 r179779 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 42 42 namespace WebKit { 43 43 44 static const char* networkCacheSubdirectory = "WebKitCache"; 44 static const char networkCacheSubdirectory[] = "WebKitCache"; 45 static const char versionDirectoryPrefix[] = "Version "; 45 46 46 47 template <typename Function> … … 67 68 String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName); 68 69 traverseDirectory(partitionPath, DT_REG, [&function, &partitionPath](const String& fileName) { 69 if (fileName.length() != 8)70 if (fileName.length() != NetworkCacheKey::hashStringLength()) 70 71 return; 71 72 function(fileName, partitionPath); … … 117 118 } 118 119 119 NetworkCacheStorage::NetworkCacheStorage(const String& directoryPath) 120 : m_directoryPath(directoryPath) 120 static String makeVersionedDirectoryPath(const String& baseDirectoryPath) 121 { 122 String versionSubdirectory = versionDirectoryPrefix + String::number(NetworkCacheStorage::version); 123 return WebCore::pathByAppendingComponent(baseDirectoryPath, versionSubdirectory); 124 } 125 126 NetworkCacheStorage::NetworkCacheStorage(const String& baseDirectoryPath) 127 : m_baseDirectoryPath(baseDirectoryPath) 128 , m_directoryPath(makeVersionedDirectoryPath(baseDirectoryPath)) 121 129 , m_ioQueue(adoptDispatch(dispatch_queue_create("com.apple.WebKit.Cache.Storage", DISPATCH_QUEUE_CONCURRENT))) 122 130 , m_backgroundIOQueue(adoptDispatch(dispatch_queue_create("com.apple.WebKit.Cache.Storage.Background", DISPATCH_QUEUE_CONCURRENT))) … … 124 132 dispatch_set_target_queue(m_backgroundIOQueue.get(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); 125 133 134 deleteOldVersions(); 126 135 initialize(); 127 136 } … … 140 149 if (!NetworkCacheKey::stringToHash(fileName, hash)) 141 150 return; 142 dispatch_async(dispatch_get_main_queue(), [this, hash] { 143 m_contentsFilter.add(hash); 151 unsigned shortHash = NetworkCacheKey::toShortHash(hash); 152 dispatch_async(dispatch_get_main_queue(), [this, shortHash] { 153 m_contentsFilter.add(shortHash); 144 154 }); 145 155 ++entryCount; … … 345 355 ASSERT(RunLoop::isMain()); 346 356 347 if (m_contentsFilter.mayContain(key. hash()))348 m_contentsFilter.remove(key. hash());357 if (m_contentsFilter.mayContain(key.shortHash())) 358 m_contentsFilter.remove(key.shortHash()); 349 359 350 360 StringCapture filePathCapture(filePathForKey(key, m_directoryPath)); … … 431 441 ASSERT(priority <= maximumRetrievePriority); 432 442 433 if (!m_contentsFilter.mayContain(key. hash())) {443 if (!m_contentsFilter.mayContain(key.shortHash())) { 434 444 completionHandler(nullptr); 435 445 return; … … 450 460 ASSERT(RunLoop::isMain()); 451 461 452 m_contentsFilter.add(key. hash());462 m_contentsFilter.add(key.shortHash()); 453 463 ++m_approximateEntryCount; 454 464 … … 471 481 LOG(NetworkCacheStorage, "(NetworkProcess) write complete error=%d", error); 472 482 if (error) { 473 if (m_contentsFilter.mayContain(store.key. hash()))474 m_contentsFilter.remove(store.key. hash());483 if (m_contentsFilter.mayContain(store.key.shortHash())) 484 m_contentsFilter.remove(store.key.shortHash()); 475 485 if (m_approximateEntryCount) 476 486 --m_approximateEntryCount; … … 494 504 ASSERT(RunLoop::isMain()); 495 505 496 if (!m_contentsFilter.mayContain(key. hash())) {506 if (!m_contentsFilter.mayContain(key.shortHash())) { 497 507 LOG(NetworkCacheStorage, "(NetworkProcess) existing entry not found, storing full entry"); 498 508 store(key, updateEntry, WTF::move(completionHandler)); … … 600 610 if (!NetworkCacheKey::stringToHash(fileName, hash)) 601 611 return; 602 dispatch_async(dispatch_get_main_queue(), [this, hash] { 603 if (m_contentsFilter.mayContain(hash)) 604 m_contentsFilter.remove(hash); 612 unsigned shortHash = NetworkCacheKey::toShortHash(hash); 613 dispatch_async(dispatch_get_main_queue(), [this, shortHash] { 614 if (m_contentsFilter.mayContain(shortHash)) 615 m_contentsFilter.remove(shortHash); 605 616 }); 606 617 }); … … 612 623 } 613 624 625 void NetworkCacheStorage::deleteOldVersions() 626 { 627 // Delete V1 cache. 628 StringCapture cachePathCapture(m_baseDirectoryPath); 629 dispatch_async(m_backgroundIOQueue.get(), [cachePathCapture] { 630 String cachePath = cachePathCapture.string(); 631 traverseDirectory(cachePath, DT_DIR, [&cachePath](const String& subdirName) { 632 if (subdirName.startsWith(versionDirectoryPrefix)) 633 return; 634 String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName); 635 traverseDirectory(partitionPath, DT_REG, [&partitionPath](const String& fileName) { 636 WebCore::deleteFile(WebCore::pathByAppendingComponent(partitionPath, fileName)); 637 }); 638 WebCore::deleteEmptyDirectory(partitionPath); 639 }); 640 }); 641 } 642 614 643 } 615 644
Note:
See TracChangeset
for help on using the changeset viewer.