diff options
| author | ruki <[email protected]> | 2025-10-02 19:09:25 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-10-02 19:09:25 +0800 |
| commit | c62972f4def074c8b0b433e557a48d313bf77a18 (patch) | |
| tree | 0a24c95b7e5f3b2c0b73c3a8857b77dee04842ea | |
| parent | 553eceaccbddb35e8499b3a4332a5b798219f796 (diff) | |
| parent | 6377f4494967e341150f0e2bb042d3c7d8bd15c9 (diff) | |
Merge pull request #6872 from xmake-io/opti
Improve hash
| m--------- | core/src/tbox/tbox | 0 | ||||
| -rw-r--r-- | core/src/xmake/engine.c | 16 | ||||
| -rw-r--r-- | core/src/xmake/hash/md5.c | 13 | ||||
| -rw-r--r-- | core/src/xmake/hash/prefix.h | 22 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand128.c | 55 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand32.c | 52 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand64.c | 51 | ||||
| -rw-r--r-- | core/src/xmake/hash/sha.c | 11 | ||||
| -rw-r--r-- | core/src/xmake/hash/xxhash.c | 44 | ||||
| -rw-r--r-- | tests/benchmarks/hash.lua | 214 | ||||
| -rw-r--r-- | xmake/actions/config/configfiles.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/hash.lua | 70 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 3 | ||||
| -rw-r--r-- | xmake/core/base/scheduler.lua | 2 | ||||
| -rw-r--r-- | xmake/core/package/package.lua | 8 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 4 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/hash.lua | 79 | ||||
| -rw-r--r-- | xmake/modules/private/cache/build_cache.lua | 2 | ||||
| -rw-r--r-- | xmake/plugins/project/cmake/cmakelists.lua | 4 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/support.lua | 4 | ||||
| -rw-r--r-- | xmake/rules/c++/unity_build/unity_build.lua | 2 |
21 files changed, 587 insertions, 71 deletions
diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox -Subproject b4c7e09b76751eacb7afa1521ac688e54b9cc76 +Subproject 46f5987ad31f4a52ee99417d62196f9bb524835 diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 203fc1d49..c3f8e9f5c 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -225,6 +225,9 @@ tb_int_t xm_hash_uuid4(lua_State* lua); tb_int_t xm_hash_sha(lua_State* lua); tb_int_t xm_hash_md5(lua_State* lua); tb_int_t xm_hash_xxhash(lua_State* lua); +tb_int_t xm_hash_rand32(lua_State* lua); +tb_int_t xm_hash_rand64(lua_State* lua); +tb_int_t xm_hash_rand128(lua_State* lua); // the base64 functions tb_int_t xm_base64_encode(lua_State* lua); @@ -518,11 +521,14 @@ static luaL_Reg const g_path_functions[] = // the hash functions static luaL_Reg const g_hash_functions[] = { - { "uuid4", xm_hash_uuid4 } -, { "sha", xm_hash_sha } -, { "md5", xm_hash_md5 } -, { "xxhash", xm_hash_xxhash } -, { tb_null, tb_null } + { "uuid4", xm_hash_uuid4 } +, { "sha", xm_hash_sha } +, { "md5", xm_hash_md5 } +, { "xxhash", xm_hash_xxhash } +, { "rand32", xm_hash_rand32 } +, { "rand64", xm_hash_rand64 } +, { "rand128", xm_hash_rand128 } +, { tb_null, tb_null } }; // the base64 functions diff --git a/core/src/xmake/hash/md5.c b/core/src/xmake/hash/md5.c index 1ca594941..39fa82b15 100644 --- a/core/src/xmake/hash/md5.c +++ b/core/src/xmake/hash/md5.c @@ -57,10 +57,10 @@ tb_int_t xm_hash_md5(lua_State* lua) // make md5 string tb_char_t s[256]; - xm_hash_make_cstr(s, buffer, 16); + tb_size_t n = xm_hash_make_cstr(s, buffer, 16); // save result - lua_pushstring(lua, s); + lua_pushlstring(lua, s, n); return 1; } @@ -108,14 +108,11 @@ tb_int_t xm_hash_md5(lua_State* lua) tb_md5_exit(&md5, buffer, sizeof(buffer)); // make md5 string - tb_size_t i = 0; - tb_char_t s[256] = {0}; - for (i = 0; i < 16; ++i) tb_snprintf(s + (i << 1), 3, "%02x", buffer[i]); + tb_char_t s[256]; + tb_size_t n = xm_hash_make_cstr(s, buffer, 16); // save result - lua_pushstring(lua, s); - - // ok + lua_pushlstring(lua, s, n); ok = tb_true; } diff --git a/core/src/xmake/hash/prefix.h b/core/src/xmake/hash/prefix.h index f5374a2d1..8a321e1eb 100644 --- a/core/src/xmake/hash/prefix.h +++ b/core/src/xmake/hash/prefix.h @@ -30,7 +30,26 @@ * helper implementation */ -static __tb_inline__ tb_void_t xm_hash_make_cstr(tb_char_t hash[256], tb_byte_t const* data, tb_size_t size) +static __tb_inline__ tb_uint64_t xm_hash_xorshift64(tb_uint64_t x) +{ + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + return x; +} + +// http://xorshift.di.unimi.it/xorshift128plus.c +static __tb_inline__ tb_uint64_t xm_hash_xorshift128(tb_uint64_t* s) +{ + tb_uint64_t s1 = s[0]; + tb_uint64_t const s0 = s[1]; + s[0] = s0; + s1 ^= s1 << 23; + s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); + return s[1] + s0; +} + +static __tb_inline__ tb_size_t xm_hash_make_cstr(tb_char_t hash[256], tb_byte_t const* data, tb_size_t size) { static tb_char_t const* digits_table = "0123456789abcdef"; tb_size_t i = 0; @@ -44,6 +63,7 @@ static __tb_inline__ tb_void_t xm_hash_make_cstr(tb_char_t hash[256], tb_byte_t s += 2; } *s = '\0'; + return s - hash; } #endif diff --git a/core/src/xmake/hash/rand128.c b/core/src/xmake/hash/rand128.c new file mode 100644 index 000000000..1e1f34fde --- /dev/null +++ b/core/src/xmake/hash/rand128.c @@ -0,0 +1,55 @@ +/*!A cross-platform build utility based on Lua + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015-present, Xmake Open Source Community. + * + * @author ruki + * @file rand128.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "rand128" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_hash_rand128(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + static union { tb_byte_t b[16]; tb_uint64_t word[2]; } s_seed = {0}; + if (!s_seed.word[0] && !s_seed.word[1]) + { + s_seed.word[0] = (tb_uint64_t)tb_uclock(); + s_seed.word[1] = (tb_uint64_t)tb_uclock(); + } + s_seed.word[0] = xm_hash_xorshift128(s_seed.word); + s_seed.word[1] = xm_hash_xorshift128(s_seed.word); + + tb_char_t s[256]; + tb_size_t n = xm_hash_make_cstr(s, s_seed.b, 16); + + lua_pushlstring(lua, s, n); + return 1; +} diff --git a/core/src/xmake/hash/rand32.c b/core/src/xmake/hash/rand32.c new file mode 100644 index 000000000..bbf565acd --- /dev/null +++ b/core/src/xmake/hash/rand32.c @@ -0,0 +1,52 @@ +/*!A cross-platform build utility based on Lua + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015-present, Xmake Open Source Community. + * + * @author ruki + * @file rand32.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "rand32" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_hash_rand32(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + static tb_uint64_t s_seed = 0; + if (!s_seed) + s_seed = (tb_uint64_t)tb_uclock(); + s_seed = xm_hash_xorshift64(s_seed); + + tb_char_t s[256]; + tb_uint32_t word = (s_seed >> 32) ^ (s_seed & 0xffffffff); + tb_size_t n = xm_hash_make_cstr(s, (tb_byte_t const*)&word, 4); + + lua_pushlstring(lua, s, n); + return 1; +} diff --git a/core/src/xmake/hash/rand64.c b/core/src/xmake/hash/rand64.c new file mode 100644 index 000000000..31732bc53 --- /dev/null +++ b/core/src/xmake/hash/rand64.c @@ -0,0 +1,51 @@ +/*!A cross-platform build utility based on Lua + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015-present, Xmake Open Source Community. + * + * @author ruki + * @file rand64.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "rand64" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_hash_rand64(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + static union { tb_byte_t b[8]; tb_uint64_t word; } s_seed = {0}; + if (!s_seed.word) + s_seed.word = (tb_uint64_t)tb_uclock(); + s_seed.word = xm_hash_xorshift64(s_seed.word); + + tb_char_t s[256]; + tb_size_t n = xm_hash_make_cstr(s, s_seed.b, 8); + + lua_pushlstring(lua, s, n); + return 1; +} diff --git a/core/src/xmake/hash/sha.c b/core/src/xmake/hash/sha.c index 4ffc2651e..ba5408279 100644 --- a/core/src/xmake/hash/sha.c +++ b/core/src/xmake/hash/sha.c @@ -62,13 +62,12 @@ tb_int_t xm_hash_sha(lua_State* lua) tb_sha_exit(&sha, buffer, sizeof(buffer)); // make sha string - tb_size_t i = 0; + tb_char_t s[256]; tb_size_t n = sha.digest_len << 2; - tb_char_t s[256] = {0}; - for (i = 0; i < n; ++i) tb_snprintf(s + (i << 1), 3, "%02x", buffer[i]); + tb_size_t len = xm_hash_make_cstr(s, buffer, n); // save result - lua_pushstring(lua, s); + lua_pushlstring(lua, s, len); return 1; } @@ -118,10 +117,10 @@ tb_int_t xm_hash_sha(lua_State* lua) // make sha string tb_char_t s[256]; tb_size_t n = sha.digest_len << 2; - xm_hash_make_cstr(s, buffer, n); + tb_size_t len = xm_hash_make_cstr(s, buffer, n); // save result - lua_pushstring(lua, s); + lua_pushlstring(lua, s, len); ok = tb_true; } diff --git a/core/src/xmake/hash/xxhash.c b/core/src/xmake/hash/xxhash.c index 8f2cc630c..cf4f67e37 100644 --- a/core/src/xmake/hash/xxhash.c +++ b/core/src/xmake/hash/xxhash.c @@ -44,7 +44,7 @@ tb_int_t xm_hash_xxhash(lua_State* lua) // get mode tb_size_t mode = (tb_size_t)lua_tointeger(lua, 1); - if (mode != 64 && mode != 128) + if (mode != 32 && mode != 64 && mode != 128) { lua_pushnil(lua); lua_pushfstring(lua, "invalid mode(%d)!", (tb_int_t)mode); @@ -66,17 +66,24 @@ tb_int_t xm_hash_xxhash(lua_State* lua) // compuate hash tb_byte_t const* buffer = tb_null; + tb_uint32_t value32; XXH64_hash_t value64; XXH128_hash_t value128; - if (mode == 64) + if (mode == 128) + { + value128 = XM_XXH3_128bits(data, size); + buffer = (tb_byte_t const*)&value128; + } + else if (mode == 64) { value64 = XM_XXH3_64bits(data, size); buffer = (tb_byte_t const*)&value64; } - else if (mode == 128) + else if (mode == 32) { - value128 = XM_XXH3_128bits(data, size); - buffer = (tb_byte_t const*)&value128; + value64 = XM_XXH3_64bits(data, size); + value32 = (value64 >> 32) ^ (value64 & 0xffffffff); + buffer = (tb_byte_t const*)&value32; } if (!buffer) { @@ -88,10 +95,10 @@ tb_int_t xm_hash_xxhash(lua_State* lua) // make xxhash string tb_char_t s[256]; tb_size_t n = mode >> 3; - xm_hash_make_cstr(s, buffer, n); + tb_size_t len = xm_hash_make_cstr(s, buffer, n); // save result - lua_pushstring(lua, s); + lua_pushlstring(lua, s, len); return 1; } @@ -109,7 +116,7 @@ tb_int_t xm_hash_xxhash(lua_State* lua) if (tb_stream_open(stream) && state) { // reset xxhash - if (mode == 64) XM_XXH3_64bits_reset(state); + if (mode == 32 || mode == 64) XM_XXH3_64bits_reset(state); else XM_XXH3_128bits_reset(state); // read data and update xxhash @@ -122,7 +129,7 @@ tb_int_t xm_hash_xxhash(lua_State* lua) // ok? if (real > 0) { - if (mode == 64) XM_XXH3_64bits_update(state, data, real); + if (mode == 32 || mode == 64) XM_XXH3_64bits_update(state, data, real); else XM_XXH3_128bits_update(state, data, real); } // no data? continue it @@ -141,26 +148,33 @@ tb_int_t xm_hash_xxhash(lua_State* lua) // compuate hash tb_byte_t const* buffer; + tb_uint32_t value32; XXH64_hash_t value64; XXH128_hash_t value128; - if (mode == 64) + if (mode == 128) + { + value128 = XM_XXH3_128bits_digest(state); + buffer = (tb_byte_t const*)&value128; + } + else if (mode == 64) { value64 = XM_XXH3_64bits_digest(state); buffer = (tb_byte_t const*)&value64; } - else + else if (mode == 32) { - value128 = XM_XXH3_128bits_digest(state); - buffer = (tb_byte_t const*)&value128; + value64 = XM_XXH3_64bits_digest(state); + value32 = (value64 >> 32) ^ (value64 & 0xffffffff); + buffer = (tb_byte_t const*)&value32; } // make xxhash string tb_char_t s[256]; tb_size_t n = mode >> 3; - xm_hash_make_cstr(s, buffer, n); + tb_size_t len = xm_hash_make_cstr(s, buffer, n); // save result - lua_pushstring(lua, s); + lua_pushlstring(lua, s, len); ok = tb_true; } diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua new file mode 100644 index 000000000..0f33684a0 --- /dev/null +++ b/tests/benchmarks/hash.lua @@ -0,0 +1,214 @@ +import("core.base.bytes") + +local COUNT = 1000000 + +function test_md5(data) + data = bytes(data) + local h + local n = COUNT / 10000 + local t = os.mclock() + for i = 1, n do + h = hash.md5(data) + end + t = os.mclock() - t + print("md5(%d): %d ms, hash: %s", COUNT, t * 10000, h) +end + +function test_sha1(data) + data = bytes(data) + local h + local n = COUNT / 10000 + local t = os.mclock() + for i = 1, n do + h = hash.sha1(data) + end + t = os.mclock() - t + print("sha1(%d): %d ms, hash: %s", COUNT, t * 10000, h) +end + +function test_sha256(data) + data = bytes(data) + local h + local n = COUNT / 10000 + local t = os.mclock() + for i = 1, n do + h = hash.sha256(data) + end + t = os.mclock() - t + print("sha256(%d): %d ms, hash: %s", COUNT, t * 10000, h) +end + +function test_uuid(data) + local h + local n = COUNT / 10000 + local t = os.mclock() + for i = 1, n do + h = hash.uuid(data) + end + t = os.mclock() - t + print("uuid(%d): %d ms, hash: %s", COUNT, t * 10000, h) +end + +function test_xxhash32(data) + data = bytes(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.xxhash32(data) + end + t = os.mclock() - t + print("xxhash32(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_xxhash64(data) + data = bytes(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.xxhash64(data) + end + t = os.mclock() - t + print("xxhash64(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_xxhash128(data) + data = bytes(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.xxhash128(data) + end + t = os.mclock() - t + print("xxhash128(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_strhash32(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.strhash32(data) + end + t = os.mclock() - t + print("strhash32(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_strhash64(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.strhash64(data) + end + t = os.mclock() - t + print("strhash64(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_strhash128(data) + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.strhash128(data) + end + t = os.mclock() - t + print("strhash128(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_random_uuid() + local h + local n = COUNT / 1000 + local t = os.mclock() + for i = 1, n do + h = hash.uuid() + end + t = os.mclock() - t + print("uuid(%d): %d ms, hash: %s", COUNT, t * 1000, h) +end + +function test_rand32() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.rand32() + end + t = os.mclock() - t + print("rand32(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_rand64() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.rand64() + end + t = os.mclock() - t + print("rand64(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_rand128() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.rand128() + end + t = os.mclock() - t + print("rand128(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_longstr() + print("========================================== test long string ==========================================") + local data = "" + for i = 1, 10000 do + data = data .. "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + end + test_md5(data) + test_sha1(data) + test_sha256(data) + test_uuid(data) + test_xxhash32(data) + test_xxhash64(data) + test_xxhash128(data) + test_strhash32(data) + test_strhash64(data) + test_strhash128(data) +end + +function test_shortstr() + print("========================================== test short string ==========================================") + COUNT = COUNT * 100 + local data = "" + for i = 1, 10 do + data = data .. "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + end + test_md5(data) + test_sha1(data) + test_sha256(data) + test_uuid(data) + test_xxhash32(data) + test_xxhash64(data) + test_xxhash128(data) + test_strhash32(data) + test_strhash64(data) + test_strhash128(data) +end + +function test_random() + print("========================================== test random ==========================================") + test_random_uuid() + test_rand32() + test_rand64() + test_rand128() +end + +function main() + test_longstr() + test_shortstr() + test_random() +end diff --git a/xmake/actions/config/configfiles.lua b/xmake/actions/config/configfiles.lua index ce435d774..60e5ef378 100644 --- a/xmake/actions/config/configfiles.lua +++ b/xmake/actions/config/configfiles.lua @@ -292,7 +292,7 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets, preprocessors end else -- generate to the temporary file first - local dstfile_tmp = path.join(os.tmpdir(), hash.uuid4(srcfile)) + local dstfile_tmp = os.tmpfile(srcfile) os.tryrm(dstfile_tmp) os.cp(srcfile, dstfile_tmp) diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index 362eb67e5..e846ba302 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -25,11 +25,15 @@ local hash = hash or {} local io = require("base/io") local utils = require("base/utils") local bytes = require("base/bytes") +local libc = require("base/libc") -- save metatable and builtin functions hash._md5 = hash._md5 or hash.md5 hash._sha = hash._sha or hash.sha hash._xxhash = hash._xxhash or hash.xxhash +hash._rand32 = hash._rand32 or hash.rand32 +hash._rand64 = hash._rand64 or hash.rand64 +hash._rand128 = hash._rand128 or hash.rand128 -- generate md5 from the given file or data function hash.md5(file_or_data) @@ -70,6 +74,24 @@ function hash.sha256(file_or_data) return hashstr, errors end +-- generate uuid, e.g "91E8ECF1-417F-4EDF-A574-E22D7D8D204A" +function hash.uuid(str) + return hash.uuid4(str) +end + +-- generate xxhash32 from the given file or data +function hash.xxhash32(file_or_data) + local hashstr, errors + if bytes.instance_of(file_or_data) then + local datasize = file_or_data:size() + local dataaddr = file_or_data:caddr() + hashstr, errors = hash._xxhash(32, dataaddr, datasize) + else + hashstr, errors = hash._xxhash(32, file_or_data) + end + return hashstr, errors +end + -- generate xxhash64 from the given file or data function hash.xxhash64(file_or_data) local hashstr, errors @@ -96,20 +118,52 @@ function hash.xxhash128(file_or_data) return hashstr, errors end --- generate uuid, e.g "91E8ECF1-417F-4EDF-A574-E22D7D8D204A" -function hash.uuid(str) - return hash.uuid4(str) -end - --- TODO, we should optimize it -- generate hash32 from string, e.g. "91e8ecf1" function hash.strhash32(str) - return hash.uuid4(str):split("-", {plain = true})[1]:lower() + local data = libc.ptraddr(libc.dataptr(str)) + local size = #str + return hash._xxhash(32, data, size) +end + +-- generate hash64 from string, e.g. "91e8ecf191e8ecf1" +function hash.strhash64(str) + local data = libc.ptraddr(libc.dataptr(str)) + local size = #str + return hash._xxhash(64, data, size) end -- generate hash128 from string, e.g. "91e8ecf1417f4edfa574e22d7d8d204a" function hash.strhash128(str) - return hash.uuid4(str):replace("-", "", {plain = true}):lower() + local data = libc.ptraddr(libc.dataptr(str)) + local size = #str + return hash._xxhash(128, data, size) +end + +-- generate random32 hash +function hash.rand32() + if hash._rand32 then + return hash._rand32() + else + return hash.strhash32(tostring(math.random())) + end +end + +-- generate random64 hash +function hash.rand64() + if hash._rand64 then + return hash._rand64() + else + return hash.strhash64(tostring(math.random())) + end +end + +-- generate random128 hash +function hash.rand128() + if hash._rand128 then + return hash._rand128() + else + return hash.strhash128(tostring(math.random())) + end end -- return module: hash diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 41fe07d22..988d9e4bf 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -761,7 +761,8 @@ function os.tmpfile(opt_or_key) key = opt_or_key.key opt = opt_or_key end - return path.join(os.tmpdir(opt), "_" .. (hash.uuid4(key):gsub("-", ""))) + local filename = "_" .. (key and hash.strhash128(key) or (hash.rand128())) + return path.join(os.tmpdir(opt), filename) end -- exit program diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index c96b32441..63c9fe009 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -299,7 +299,7 @@ function scheduler:_co_curenvs_update(envs) for _, key in ipairs(table.orderkeys(envs)) do envs_hash = envs_hash .. key:upper() .. envs[key] end - envs_hash = hash.uuid4(envs_hash):sub(1, 8) + envs_hash = hash.strhash32(envs_hash) self._CO_CURENVS_HASH = envs_hash -- save the current directory for each coroutine diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 7a1d8e24b..db943815a 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1691,6 +1691,12 @@ function _instance:_compute_buildhash() self:buildhash() end +-- hash.strhash128 has been switched to xxhash. +-- For compatibility, the old hash algorithm is still used here. +function _instance:_strhash128(str) + return hash.uuid4(str):replace("-", "", {plain = true}):lower() +end + -- get the build hash function _instance:buildhash() local buildhash = self._BUILDHASH @@ -1752,7 +1758,7 @@ function _instance:buildhash() table.sort(toolchains) str = str .. "_" .. table.concat(toolchains, "_") end - return hash.strhash128(str) + return self:_strhash128(str) end local function _get_installdir(...) local name = self:name():lower():gsub("::", "_") diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 86050ebec..5af05c21f 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -25,6 +25,7 @@ local project = project or {} local os = require("base/os") local io = require("base/io") local path = require("base/path") +local hash = require("base/hash") local task = require("base/task") local utils = require("base/utils") local table = require("base/table") @@ -1380,7 +1381,8 @@ function project.tmpfile(opt_or_key) key = opt_or_key.key opt = opt_or_key end - return path.join(project.tmpdir(opt), "_" .. (hash.uuid4(key):gsub("-", ""))) + local filename = "_" .. (key and hash.strhash128(key) or (hash.rand128())) + return path.join(project.tmpdir(opt), "_" .. filename) end -- get all modes diff --git a/xmake/core/sandbox/modules/hash.lua b/xmake/core/sandbox/modules/hash.lua index 47235bcd6..b5927b029 100644 --- a/xmake/core/sandbox/modules/hash.lua +++ b/xmake/core/sandbox/modules/hash.lua @@ -47,7 +47,7 @@ end function sandbox_hash.sha1(file_or_data) local sha1, errors = hash.sha1(file_or_data) if not sha1 then - raise("cannot generate sha1 for %s, %s", file_or_data, errors or "unknown errors") + raise("cannot generate sha1, %s", errors or "unknown errors") end return sha1 end @@ -56,7 +56,7 @@ end function sandbox_hash.sha256(file_or_data) local sha256, errors = hash.sha256(file_or_data) if not sha256 then - raise("cannot generate sha256 for %s, %s", file_or_data, errors or "unknown errors") + raise("cannot generate sha256, %s", errors or "unknown errors") end return sha256 end @@ -65,45 +65,90 @@ end function sandbox_hash.md5(file_or_data) local md5, errors = hash.md5(file_or_data) if not md5 then - raise("cannot generate md5 for %s, %s", file_or_data, errors or "unknown errors") + raise("cannot generate md5, %s", errors or "unknown errors") end return md5 end +-- generate xxhash32 from the given file or data +function sandbox_hash.xxhash32(file_or_data) + local result, errors = hash.xxhash32(file_or_data) + if not result then + raise("cannot generate xxhash32, %s", errors or "unknown errors") + end + return result +end + -- generate xxhash64 from the given file or data function sandbox_hash.xxhash64(file_or_data) - local xxhash64, errors = hash.xxhash64(file_or_data) - if not xxhash64 then - raise("cannot generate xxhash64 for %s, %s", file_or_data, errors or "unknown errors") + local result, errors = hash.xxhash64(file_or_data) + if not result then + raise("cannot generate xxhash64, %s", errors or "unknown errors") end - return xxhash64 + return result end -- generate xxhash128 from the given file or data function sandbox_hash.xxhash128(file_or_data) - local xxhash128, errors = hash.xxhash128(file_or_data) - if not xxhash128 then - raise("cannot generate xxhash128 for %s, %s", file_or_data, errors or "unknown errors") + local result, errors = hash.xxhash128(file_or_data) + if not result then + raise("cannot generate xxhash128, %s", errors or "unknown errors") end - return xxhash128 + return result end -- generate hash32 from string function sandbox_hash.strhash32(str) - local hash32, errors = hash.strhash32(str) - if not hash32 then + local result, errors = hash.strhash32(str) + if not result then + raise("cannot generate hash32 for %s, %s", str, errors or "unknown errors") + end + return result +end + +-- generate hash64 from string +function sandbox_hash.strhash64(str) + local result, errors = hash.strhash64(str) + if not result then raise("cannot generate hash32 for %s, %s", str, errors or "unknown errors") end - return hash32 + return result end -- generate hash128 from string function sandbox_hash.strhash128(str) - local hash128, errors = hash.strhash128(str) - if not hash128 then + local result, errors = hash.strhash128(str) + if not result then raise("cannot generate hash128 for %s, %s", str, errors or "unknown errors") end - return hash128 + return result +end + +-- generate random32 +function sandbox_hash.rand32() + local result, errors = hash.rand32() + if not result then + raise("cannot generate random32, %s", errors or "unknown errors") + end + return result +end + +-- generate random64 +function sandbox_hash.rand64() + local result, errors = hash.rand64() + if not result then + raise("cannot generate random64, %s", errors or "unknown errors") + end + return result +end + +-- generate random128 +function sandbox_hash.rand128() + local result, errors = hash.rand128() + if not result then + raise("cannot generate random128, %s", errors or "unknown errors") + end + return result end -- return module diff --git a/xmake/modules/private/cache/build_cache.lua b/xmake/modules/private/cache/build_cache.lua index 3b82578e5..905426ef5 100644 --- a/xmake/modules/private/cache/build_cache.lua +++ b/xmake/modules/private/cache/build_cache.lua @@ -128,7 +128,7 @@ function cachekey(program, cppinfo, envs) end end end - return hash.xxhash128(bytes(table.concat(items, ""))) + return hash.strhash128(table.concat(items, "")) end -- get cache root directory diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index a5ec312cb..a339a654e 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -1074,7 +1074,7 @@ function _add_target_link_libraries(cmakelists, target, outputdir) local has_links = #target:objectfiles() > objectfiles_set:size() - local key = target:name() .. "_" .. hash.uuid():split("-", {plain = true})[1] + local key = target:name() .. "_" .. hash.rand32() if has_links then cmakelists:print("add_library(target_objectfiles_%s OBJECT IMPORTED GLOBAL)", key) cmakelists:print("set_property(TARGET target_objectfiles_%s PROPERTY IMPORTED_OBJECTS", key) @@ -1244,7 +1244,7 @@ function _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir -- -- @see https://gitlab.kitware.com/cmake/cmake/-/issues/17802 -- - local key = target:name() .. "_" .. hash.uuid():split("-", {plain = true})[1] + local key = target:name() .. "_" .. hash.rand32() cmakelists:print("add_custom_command(OUTPUT output_%s", key) for _, cmd in ipairs(cmds) do local command = _get_command_string(cmd, outputdir) diff --git a/xmake/rules/c++/modules/support.lua b/xmake/rules/c++/modules/support.lua index 8d1c39531..cee0f1ab8 100644 --- a/xmake/rules/c++/modules/support.lua +++ b/xmake/rules/c++/modules/support.lua @@ -336,7 +336,7 @@ function modules_cachedir(target, opt) moduletype = "interfaces" elseif opt.scan then moduletype = "scans" - else + else moduletype = "implementation" end local cachedir = path.join(target:autogendir(), "rules", "bmi", "cache", moduletype) @@ -347,7 +347,7 @@ function modules_cachedir(target, opt) end function get_modulehash(sourcefile) - return hash.uuid(sourcefile):split("-", {plain = true})[1]:lower() + return hash.strhash32(sourcefile) end function get_metafile(target, module) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index e8f37f868..3df2d75b4 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -36,7 +36,7 @@ function _merge_unityfile(target, sourcefile_unity, sourcefiles, opt) sourcefile_unity = path.absolute(sourcefile_unity) sourcefile = path.relative(sourcefile, path.directory(sourcefile_unity)) if uniqueid then - unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1]) + unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.rand32()) end unityfile:print("#include \"%s\"", sourcefile) if uniqueid then |
