]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Reduce number of memory allocations in hashing (#608)
authorOlle Liljenzin <olle@liljenzin.se>
Mon, 22 Jun 2020 19:57:59 +0000 (21:57 +0200)
committerGitHub <noreply@github.com>
Mon, 22 Jun 2020 19:57:59 +0000 (21:57 +0200)
Add hash_buffer_once method for hashing a given text immediately using a
stack allocated hasher. Also skip copying the hasher in hash_result as
blake3 is not modifying the hasher.

src/InodeCache.cpp
src/hash.cpp
src/hash.hpp
unittest/test_hash.cpp

index acf0a1ee02a494756a2a44c39402c14dbfc90e70..fd5282bd076942382d7d6f2fd6e6a698f56ee551 100644 (file)
@@ -206,10 +206,7 @@ InodeCache::hash_inode(const char* path, ContentType type, Digest& digest)
 #  endif
   key.st_size = stat.size();
 
-  struct hash* hash = hash_init();
-  hash_buffer(hash, &key, sizeof(Key));
-  digest = hash_result(hash);
-  hash_free(hash);
+  digest = hash_buffer_once(&key, sizeof(Key));
   return true;
 }
 
index dcb26e79facecd99f110ee674ae014dfe205fb23..c843b685cb920a88c72eb3c5de61f07a052d7137 100644 (file)
@@ -100,14 +100,25 @@ hash_buffer(struct hash* hash, const void* s, size_t len)
   do_debug_text(hash, s, len);
 }
 
+Digest
+hash_buffer_once(const void* s, size_t len)
+{
+  blake3_hasher hasher;
+  blake3_hasher_init(&hasher);
+  blake3_hasher_update(&hasher, s, len);
+
+  Digest digest;
+  blake3_hasher_finalize(&hasher, digest.bytes(), digest.size());
+  return digest;
+}
+
 Digest
 hash_result(struct hash* hash)
 {
-  // make a copy before altering state
-  struct hash* copy = hash_copy(hash);
+  // Note that blake3_hasher_finalize doesn't modify the hasher itself, thus it
+  // is possible to finalize again after more data has been added.
   Digest digest;
-  blake3_hasher_finalize(&copy->hasher, digest.bytes(), digest.size());
-  hash_free(copy);
+  blake3_hasher_finalize(&hash->hasher, digest.bytes(), digest.size());
   return digest;
 }
 
index 557d648a38355be82a0f4ab4c0fdb1aef11423f7..5a104af5d0e74915b884f49be60930520a06a646 100644 (file)
@@ -61,6 +61,11 @@ void hash_delimiter(struct hash* hash, const char* type);
 // input file.
 void hash_buffer(struct hash* hash, const void* s, size_t len);
 
+// Hash bytes in a buffer.
+//
+// Returns the digest.
+Digest hash_buffer_once(const void* s, size_t len);
+
 // Hash a NUL terminated string.
 //
 // If hash debugging is enabled, the string is written to the text input file
index b8093038f08e03523d5fd6b4a35f1e23c6f79db8..04e8c8adbfa9c1ec058e7c78698ed1e819b97c1b 100644 (file)
@@ -93,3 +93,9 @@ TEST_CASE("hash_result digest bytes")
   CHECK(memcmp(d.bytes(), expected, sizeof(Digest::size())) == 0);
   hash_free(h);
 }
+
+TEST_CASE("hash_once")
+{
+  CHECK(hash_buffer_once("a", 1).to_string()
+        == "17762fddd969a453925d65717ac3eea21320b66b");
+}