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

Side by Side Diff: src/core/SkChecksum.h

Issue 1021033002: Some usability ideas around SkTHash. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: minor tweaks Created 5 years, 9 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
« no previous file with comments | « dm/DM.cpp ('k') | src/core/SkTHash.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkChecksum_DEFINED 8 #ifndef SkChecksum_DEFINED
9 #define SkChecksum_DEFINED 9 #define SkChecksum_DEFINED
10 10
11 #include "SkString.h"
12 #include "SkTLogic.h"
11 #include "SkTypes.h" 13 #include "SkTypes.h"
12 14
13 /** 15 /**
14 * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant 16 * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant
15 * to be very very fast, as it is used internally by the font cache, in 17 * to be very very fast, as it is used internally by the font cache, in
16 * conjuction with the entire raw key. This algorithm does not generate 18 * conjuction with the entire raw key. This algorithm does not generate
17 * unique values as well as others (e.g. MD5) but it performs much faster. 19 * unique values as well as others (e.g. MD5) but it performs much faster.
18 * Skia's use cases can survive non-unique values (since the entire key is 20 * Skia's use cases can survive non-unique values (since the entire key is
19 * always available). Clients should only be used in circumstances where speed 21 * always available). Clients should only be used in circumstances where speed
20 * over uniqueness is at a premium. 22 * over uniqueness is at a premium.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 hash *= 0x85ebca6b; 64 hash *= 0x85ebca6b;
63 hash ^= hash >> 16; 65 hash ^= hash >> 16;
64 return hash; 66 return hash;
65 } 67 }
66 68
67 /** 69 /**
68 * Calculate 32-bit Murmur hash (murmur3). 70 * Calculate 32-bit Murmur hash (murmur3).
69 * This should take 2-3x longer than SkChecksum::Compute, but is a considera bly better hash. 71 * This should take 2-3x longer than SkChecksum::Compute, but is a considera bly better hash.
70 * See en.wikipedia.org/wiki/MurmurHash. 72 * See en.wikipedia.org/wiki/MurmurHash.
71 * 73 *
72 * @param data Memory address of the data block to be processed. Must be 32 -bit aligned. 74 * @param data Memory address of the data block to be processed.
73 * @param size Size of the data block in bytes. Must be a multiple of 4. 75 * @param size Size of the data block in bytes.
74 * @param seed Initial hash seed. (optional) 76 * @param seed Initial hash seed. (optional)
75 * @return hash result 77 * @return hash result
76 */ 78 */
77 static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) { 79 static uint32_t Murmur3(const void* data, size_t bytes, uint32_t seed=0) {
78 // Use may_alias to remind the compiler we're intentionally violating st rict aliasing, 80 // Use may_alias to remind the compiler we're intentionally violating st rict aliasing,
79 // and so not to apply strict-aliasing-based optimizations. 81 // and so not to apply strict-aliasing-based optimizations.
80 typedef uint32_t SK_ATTRIBUTE(may_alias) aliased_uint32_t; 82 typedef uint32_t SK_ATTRIBUTE(may_alias) aliased_uint32_t;
83 typedef uint8_t SK_ATTRIBUTE(may_alias) aliased_uint8_t;
84
85 // Handle 4 bytes at a time while possible.
81 const aliased_uint32_t* safe_data = (const aliased_uint32_t*)data; 86 const aliased_uint32_t* safe_data = (const aliased_uint32_t*)data;
82
83 SkASSERTF(SkIsAlign4(bytes), "Expected 4-byte multiple, got %zu", bytes) ;
84 const size_t words = bytes/4; 87 const size_t words = bytes/4;
85
86
87 uint32_t hash = seed; 88 uint32_t hash = seed;
88 for (size_t i = 0; i < words; i++) { 89 for (size_t i = 0; i < words; i++) {
89 uint32_t k = safe_data[i]; 90 uint32_t k = safe_data[i];
90 k *= 0xcc9e2d51; 91 k *= 0xcc9e2d51;
91 k = (k << 15) | (k >> 17); 92 k = (k << 15) | (k >> 17);
92 k *= 0x1b873593; 93 k *= 0x1b873593;
93 94
94 hash ^= k; 95 hash ^= k;
95 hash = (hash << 13) | (hash >> 19); 96 hash = (hash << 13) | (hash >> 19);
96 hash *= 5; 97 hash *= 5;
97 hash += 0xe6546b64; 98 hash += 0xe6546b64;
98 } 99 }
100
101 // Handle last 0-3 bytes.
102 const aliased_uint8_t* safe_tail = (const uint8_t*)(safe_data + words);
103 uint32_t k = 0;
104 switch (bytes & 3) {
105 case 3: k ^= safe_tail[2] << 16;
106 case 2: k ^= safe_tail[1] << 8;
107 case 1: k ^= safe_tail[0] << 0;
108 k *= 0xcc9e2d51;
109 k = (k << 15) | (k >> 17);
110 k *= 0x1b873593;
111 hash ^= k;
112 }
113
99 hash ^= bytes; 114 hash ^= bytes;
100 return Mix(hash); 115 return Mix(hash);
101 } 116 }
102 117
103 /** 118 /**
104 * Compute a 32-bit checksum for a given data block 119 * Compute a 32-bit checksum for a given data block
105 * 120 *
106 * WARNING: this algorithm is tuned for efficiency, not backward/forward 121 * WARNING: this algorithm is tuned for efficiency, not backward/forward
107 * compatibility. It may change at any time, so a checksum generated with 122 * compatibility. It may change at any time, so a checksum generated with
108 * one version of the Skia code may not match a checksum generated with 123 * one version of the Skia code may not match a checksum generated with
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 * since >>32 is undefined for 32bit ints, hence the wacky HALFBITS 173 * since >>32 is undefined for 32bit ints, hence the wacky HALFBITS
159 * define. 174 * define.
160 */ 175 */
161 if (8 == sizeof(result)) { 176 if (8 == sizeof(result)) {
162 result ^= result >> HALFBITS; 177 result ^= result >> HALFBITS;
163 } 178 }
164 return static_cast<uint32_t>(result); 179 return static_cast<uint32_t>(result);
165 } 180 }
166 }; 181 };
167 182
183 // SkGoodHash should usually be your first choice in hashing data.
184 // It should be both reasonably fast and high quality.
185
186 template <typename K>
187 uint32_t SkGoodHash(const K& k) {
188 if (sizeof(K) == 4) {
189 return SkChecksum::Mix(*(const uint32_t*)&k);
190 }
191 return SkChecksum::Murmur3(&k, sizeof(K));
192 }
193
194 inline uint32_t SkGoodHash(const SkString& k) {
195 return SkChecksum::Murmur3(k.c_str(), k.size());
196 }
197
168 #endif 198 #endif
OLDNEW
« no previous file with comments | « dm/DM.cpp ('k') | src/core/SkTHash.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698