From aced9c7ece3127676e9cb25d2161ff08e5560149 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 00:50:15 +0800 Subject: add hash benchmarks --- tests/benchmarks/hash.lua | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/benchmarks/hash.lua diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua new file mode 100644 index 000000000..ae8a29d21 --- /dev/null +++ b/tests/benchmarks/hash.lua @@ -0,0 +1,82 @@ +local COUNT = 1000000 + +function test_md5(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.md5(data) + end + t = os.mclock() - t + print("md5(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_sha1(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.sha1(data) + end + t = os.mclock() - t + print("sha1(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_sha256(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.sha256(data) + end + t = os.mclock() - t + print("sha256(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_uuid(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.uuid(data) + end + t = os.mclock() - t + print("uuid(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_uuid4(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.uuid4(data) + end + t = os.mclock() - t + print("uuid4(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_strhash32(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.strhash32(data) + end + t = os.mclock() - t + print("strhash32(%d): %d ms, hash: %s", COUNT, t, h) +end + +function test_strhash128(data) + local h + local t = os.mclock() + for i = 1, COUNT do + h = hash.strhash128(data) + end + t = os.mclock() - t + print("strhash128(%d): %d ms, hash: %s", COUNT, t, h) +end + +function main() + local data = io.readfile(os.programfile()) + --test_md5(data) + --test_sha1(data) + --test_sha256(data) + test_uuid(data) + test_uuid4(data) + test_strhash32(data) + test_strhash128(data) +end -- cgit v1.3.1 From d673b3732b66ddae22a5c2b3c613af5447d23dca Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 00:53:37 +0800 Subject: improve hash tests --- core/src/xmake/hash/md5.c | 5 ++-- tests/benchmarks/hash.lua | 52 ++++++++++++++++++++++++++++++------- xmake/core/sandbox/modules/hash.lua | 10 +++---- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/core/src/xmake/hash/md5.c b/core/src/xmake/hash/md5.c index 1ca594941..0f6a9f598 100644 --- a/core/src/xmake/hash/md5.c +++ b/core/src/xmake/hash/md5.c @@ -108,9 +108,8 @@ 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]; + xm_hash_make_cstr(s, buffer, 16); // save result lua_pushstring(lua, s); diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index ae8a29d21..119f1bb71 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -1,33 +1,41 @@ +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, COUNT do + for i = 1, n do h = hash.md5(data) end t = os.mclock() - t - print("md5(%d): %d ms, hash: %s", COUNT, t, h) + 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, COUNT do + for i = 1, n do h = hash.sha1(data) end t = os.mclock() - t - print("sha1(%d): %d ms, hash: %s", COUNT, t, h) + 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, COUNT do + for i = 1, n do h = hash.sha256(data) end t = os.mclock() - t - print("sha256(%d): %d ms, hash: %s", COUNT, t, h) + print("sha256(%d): %d ms, hash: %s", COUNT, t * 10000, h) end function test_uuid(data) @@ -50,6 +58,30 @@ function test_uuid4(data) print("uuid4(%d): %d ms, hash: %s", COUNT, t, 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 t = os.mclock() @@ -72,11 +104,13 @@ end function main() local data = io.readfile(os.programfile()) - --test_md5(data) - --test_sha1(data) - --test_sha256(data) + test_md5(data) + test_sha1(data) + test_sha256(data) test_uuid(data) test_uuid4(data) + test_xxhash64(data) + test_xxhash128(data) test_strhash32(data) test_strhash128(data) end diff --git a/xmake/core/sandbox/modules/hash.lua b/xmake/core/sandbox/modules/hash.lua index 47235bcd6..11a85f3fb 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,7 +65,7 @@ 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 @@ -74,7 +74,7 @@ end 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") + raise("cannot generate xxhash64, %s", errors or "unknown errors") end return xxhash64 end @@ -83,7 +83,7 @@ end 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") + raise("cannot generate xxhash128, %s", errors or "unknown errors") end return xxhash128 end -- cgit v1.3.1 From e225e4e8abf4a6fbf27343737a642c54f7c93643 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 00:54:25 +0800 Subject: improve hash cstr --- core/src/xmake/hash/md5.c | 10 ++++------ core/src/xmake/hash/prefix.h | 3 ++- core/src/xmake/hash/sha.c | 11 +++++------ core/src/xmake/hash/xxhash.c | 8 ++++---- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/src/xmake/hash/md5.c b/core/src/xmake/hash/md5.c index 0f6a9f598..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; } @@ -109,12 +109,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); - - // 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..cf4cb082d 100644 --- a/core/src/xmake/hash/prefix.h +++ b/core/src/xmake/hash/prefix.h @@ -30,7 +30,7 @@ * 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_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 +44,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/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..0c9dbdad7 100644 --- a/core/src/xmake/hash/xxhash.c +++ b/core/src/xmake/hash/xxhash.c @@ -88,10 +88,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; } @@ -157,10 +157,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); ok = tb_true; } -- cgit v1.3.1 From 9dd7fe46d8678216b62016b721fe084d5bad9246 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 22:35:21 +0800 Subject: update hash test --- tests/benchmarks/hash.lua | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index 119f1bb71..8c70c342a 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -40,22 +40,13 @@ end function test_uuid(data) local h + local n = COUNT / 10000 local t = os.mclock() - for i = 1, COUNT do + for i = 1, n do h = hash.uuid(data) end t = os.mclock() - t - print("uuid(%d): %d ms, hash: %s", COUNT, t, h) -end - -function test_uuid4(data) - local h - local t = os.mclock() - for i = 1, COUNT do - h = hash.uuid4(data) - end - t = os.mclock() - t - print("uuid4(%d): %d ms, hash: %s", COUNT, t, h) + print("uuid(%d): %d ms, hash: %s", COUNT, t * 10000, h) end function test_xxhash64(data) @@ -84,33 +75,59 @@ end function test_strhash32(data) local h + local n = COUNT / 10000 local t = os.mclock() - for i = 1, COUNT do + for i = 1, n do h = hash.strhash32(data) end t = os.mclock() - t - print("strhash32(%d): %d ms, hash: %s", COUNT, t, h) + print("strhash32(%d): %d ms, hash: %s", COUNT, t * 10000, h) end function test_strhash128(data) local h + local n = COUNT / 10000 local t = os.mclock() - for i = 1, COUNT do + for i = 1, n do h = hash.strhash128(data) end t = os.mclock() - t - print("strhash128(%d): %d ms, hash: %s", COUNT, t, h) + print("strhash128(%d): %d ms, hash: %s", COUNT, t * 10000, h) end -function main() - local data = io.readfile(os.programfile()) +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_uuid4(data) test_xxhash64(data) test_xxhash128(data) test_strhash32(data) test_strhash128(data) end + +function test_shortstr() + print("========================================== test short string ==========================================") + local data = "" + for i = 1, 10 do + data = data .. "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + end + test_md5(data) + test_sha1(data) + test_sha256(data) + test_uuid(data) + test_xxhash64(data) + test_xxhash128(data) + test_strhash32(data) + test_strhash128(data) +end + +function main() + test_longstr() + test_shortstr() +end -- cgit v1.3.1 From 703dec087d98946bc2ba5384d2274e588f8ee96d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 22:43:05 +0800 Subject: improve strhash --- tests/benchmarks/hash.lua | 9 +++++---- xmake/core/base/hash.lua | 4 ++-- xmake/core/package/package.lua | 8 +++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index 8c70c342a..48c360d58 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -75,24 +75,24 @@ end function test_strhash32(data) local h - local n = COUNT / 10000 + 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 * 10000, h) + print("strhash32(%d): %d ms, hash: %s", COUNT, t * 10, h) end function test_strhash128(data) local h - local n = COUNT / 10000 + 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 * 10000, h) + print("strhash128(%d): %d ms, hash: %s", COUNT, t * 10, h) end function test_longstr() @@ -113,6 +113,7 @@ end function test_shortstr() print("========================================== test short string ==========================================") + COUNT = COUNT * 100 local data = "" for i = 1, 10 do data = data .. "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index 362eb67e5..b40f7b885 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -104,12 +104,12 @@ 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() + return hash.xxhash64(bytes(str)):sub(1, 8) end -- generate hash128 from string, e.g. "91e8ecf1417f4edfa574e22d7d8d204a" function hash.strhash128(str) - return hash.uuid4(str):replace("-", "", {plain = true}):lower() + return hash.xxhash128(bytes(str)) end -- return module: hash diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 4b0ddd036..4c68f277c 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1687,6 +1687,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 @@ -1748,7 +1754,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("::", "_") -- cgit v1.3.1 From 3462dede0458b1bf755dcdb24bdc98b6f947188c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 22:45:25 +0800 Subject: improve build cache key --- xmake/core/base/hash.lua | 10 +++++++--- xmake/core/base/scheduler.lua | 2 +- xmake/modules/private/cache/build_cache.lua | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index b40f7b885..342b59e78 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -25,6 +25,7 @@ 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 @@ -101,15 +102,18 @@ 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.xxhash64(bytes(str)):sub(1, 8) + local data = libc.dataptr(str) + local size = #str + return hash._xxhash(64, data, size):sub(1, 8) end -- generate hash128 from string, e.g. "91e8ecf1417f4edfa574e22d7d8d204a" function hash.strhash128(str) - return hash.xxhash128(bytes(str)) + local data = libc.dataptr(str) + local size = #str + return hash._xxhash(128, data, size) end -- return module: hash 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/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 -- cgit v1.3.1 From c03e3c0a1d584826a070079e141374ac9963da7c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 22:53:02 +0800 Subject: update module hash --- xmake/rules/c++/modules/support.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) -- cgit v1.3.1 From b86ebe99285371dcdf08483208b7de70a7b8b050 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Sep 2025 22:58:43 +0800 Subject: fix xxhash for luajit --- xmake/core/base/hash.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index 342b59e78..53f535631 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -104,14 +104,14 @@ end -- generate hash32 from string, e.g. "91e8ecf1" function hash.strhash32(str) - local data = libc.dataptr(str) + local data = libc.ptraddr(libc.dataptr(str)) local size = #str return hash._xxhash(64, data, size):sub(1, 8) end -- generate hash128 from string, e.g. "91e8ecf1417f4edfa574e22d7d8d204a" function hash.strhash128(str) - local data = libc.dataptr(str) + local data = libc.ptraddr(libc.dataptr(str)) local size = #str return hash._xxhash(128, data, size) end -- cgit v1.3.1 From e4a2d682015b651adfcf7d7494a295c3276d7f10 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:36:38 +0800 Subject: add hash.random32/64/128 --- tests/benchmarks/hash.lua | 84 ++++++++++++++++++++++++++++++++++++- xmake/core/base/hash.lua | 58 ++++++++++++++++++++++--- xmake/core/base/os.lua | 3 +- xmake/core/sandbox/modules/hash.lua | 69 ++++++++++++++++++++++++------ 4 files changed, 193 insertions(+), 21 deletions(-) diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index 48c360d58..ee23921c6 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -49,6 +49,18 @@ function test_uuid(data) 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 @@ -84,6 +96,17 @@ function test_strhash32(data) 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 @@ -95,6 +118,50 @@ function test_strhash128(data) print("strhash128(%d): %d ms, hash: %s", COUNT, t * 10, h) end +function test_random_uuid() + local h + local n = COUNT / 10 + 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 * 10, h) +end + +function test_random32() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.random32() + end + t = os.mclock() - t + print("random32(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_random64() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.random64() + end + t = os.mclock() - t + print("random64(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + +function test_random128() + local h + local n = COUNT / 10 + local t = os.mclock() + for i = 1, n do + h = hash.random128() + end + t = os.mclock() - t + print("random128(%d): %d ms, hash: %s", COUNT, t * 10, h) +end + function test_longstr() print("========================================== test long string ==========================================") local data = "" @@ -105,9 +172,11 @@ function test_longstr() 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 @@ -122,13 +191,24 @@ function test_shortstr() 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_random32() + test_random64() + test_random128() +end + function main() - test_longstr() - test_shortstr() +-- test_longstr() +-- test_shortstr() + test_random() end diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index 53f535631..5f162af65 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -71,6 +71,20 @@ 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 result, errors = hash.xxhash64(file_or_data) + if result then + result = result:sub(1, 8) + end + return result, errors +end + -- generate xxhash64 from the given file or data function hash.xxhash64(file_or_data) local hashstr, errors @@ -97,16 +111,22 @@ 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 - -- generate hash32 from string, e.g. "91e8ecf1" function hash.strhash32(str) local data = libc.ptraddr(libc.dataptr(str)) local size = #str - return hash._xxhash(64, data, size):sub(1, 8) + local result, errors = hash._xxhash(64, data, size) + if result then + result = result:sub(1, 8) + end + return result, errors +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" @@ -116,5 +136,31 @@ function hash.strhash128(str) return hash._xxhash(128, data, size) end +-- init random seed +function hash._init_random_seed() + if hash._INIT_RANDOM_SEED == nil then + math.randomseed(os.time()) + hash._INIT_RANDOM_SEED = true + end +end + +-- generate random32 hash +function hash.random32() + return hash.strhash32(tostring(math.random())) +end + +-- generate random64 hash +function hash.random64() + return hash.strhash64(tostring(math.random())) +end + +-- generate random128 hash +function hash.random128() + return hash.strhash128(tostring(math.random())) +end + +-- init random seed first +hash._init_random_seed() + -- return module: hash return hash diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 41fe07d22..72d395d77 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.random128())) + return path.join(os.tmpdir(opt), filename) end -- exit program diff --git a/xmake/core/sandbox/modules/hash.lua b/xmake/core/sandbox/modules/hash.lua index 11a85f3fb..178bb2a5f 100644 --- a/xmake/core/sandbox/modules/hash.lua +++ b/xmake/core/sandbox/modules/hash.lua @@ -70,40 +70,85 @@ function sandbox_hash.md5(file_or_data) 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 + 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 + 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.random32() + local result, errors = hash.random32() + if not result then + raise("cannot generate random32, %s", errors or "unknown errors") + end + return result +end + +-- generate random64 +function sandbox_hash.random64() + local result, errors = hash.random64() + if not result then + raise("cannot generate random64, %s", errors or "unknown errors") + end + return result +end + +-- generate random128 +function sandbox_hash.random128() + local result, errors = hash.random128() + if not result then + raise("cannot generate random128, %s", errors or "unknown errors") + end + return result end -- return module -- cgit v1.3.1 From 4ef482175337e64d7bf2fb33abec2917c9e4fd4d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:37:42 +0800 Subject: update some uuid hashes --- xmake/actions/config/configfiles.lua | 2 +- xmake/core/project/project.lua | 4 +++- xmake/plugins/project/cmake/cmakelists.lua | 4 ++-- xmake/rules/c++/unity_build/unity_build.lua | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) 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/project/project.lua b/xmake/core/project/project.lua index 86050ebec..0f3a83bda 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.random128())) + return path.join(project.tmpdir(opt), "_" .. filename) end -- get all modes diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index a5ec312cb..ee6493cde 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.random32() 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.random32() 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++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index e8f37f868..1ced33ec8 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.random32()) end unityfile:print("#include \"%s\"", sourcefile) if uniqueid then -- cgit v1.3.1 From 22c23c90d226bcea5d98c01789725f5796f91f82 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:38:15 +0800 Subject: update test --- tests/benchmarks/hash.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index ee23921c6..14fe24cfc 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -208,7 +208,7 @@ function test_random() end function main() --- test_longstr() --- test_shortstr() + test_longstr() + test_shortstr() test_random() end -- cgit v1.3.1 From 672470e6e4ea7fd150354c131ba5fb60f7331643 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:41:01 +0800 Subject: update tests --- tests/benchmarks/hash.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index 14fe24cfc..554f3f166 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -120,13 +120,13 @@ end function test_random_uuid() local h - local n = COUNT / 10 + 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 * 10, h) + print("uuid(%d): %d ms, hash: %s", COUNT, t * 1000, h) end function test_random32() -- cgit v1.3.1 From 9dc8bb99439f4d31e3563a5865764798c2094e8e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:47:56 +0800 Subject: improve random hash --- core/src/xmake/engine.c | 16 +++++++---- core/src/xmake/hash/prefix.h | 27 ++++++++++++++++++ core/src/xmake/hash/rand128.c | 55 +++++++++++++++++++++++++++++++++++++ core/src/xmake/hash/rand32.c | 51 ++++++++++++++++++++++++++++++++++ core/src/xmake/hash/rand64.c | 51 ++++++++++++++++++++++++++++++++++ tests/benchmarks/hash.lua | 24 ++++++++-------- xmake/core/base/hash.lua | 26 ------------------ xmake/core/base/os.lua | 2 +- xmake/core/project/project.lua | 2 +- xmake/core/sandbox/modules/hash.lua | 12 ++++---- 10 files changed, 215 insertions(+), 51 deletions(-) create mode 100644 core/src/xmake/hash/rand128.c create mode 100644 core/src/xmake/hash/rand32.c create mode 100644 core/src/xmake/hash/rand64.c 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/prefix.h b/core/src/xmake/hash/prefix.h index cf4cb082d..59a3941d7 100644 --- a/core/src/xmake/hash/prefix.h +++ b/core/src/xmake/hash/prefix.h @@ -30,6 +30,33 @@ * helper implementation */ +static __tb_inline__ tb_uint32_t xm_hash_xorshift32(tb_uint32_t x) +{ + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + return x; +} + +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"; diff --git a/core/src/xmake/hash/rand128.c b/core/src/xmake/hash/rand128.c new file mode 100644 index 000000000..946d396fd --- /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_mclock(); + s_seed.word[1] = (tb_uint64_t)tb_mclock(); + } + 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..b76b0ae15 --- /dev/null +++ b/core/src/xmake/hash/rand32.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 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 union { tb_byte_t b[4]; tb_uint32_t word; } s_seed = {0}; + if (!s_seed.word) + s_seed.word = (tb_uint32_t)tb_mclock(); + s_seed.word = xm_hash_xorshift32(s_seed.word); + + tb_char_t s[64]; + tb_size_t n = xm_hash_make_cstr(s, s_seed.b, 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..a42d0eedb --- /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_mclock(); + 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/tests/benchmarks/hash.lua b/tests/benchmarks/hash.lua index 554f3f166..0f33684a0 100644 --- a/tests/benchmarks/hash.lua +++ b/tests/benchmarks/hash.lua @@ -129,37 +129,37 @@ function test_random_uuid() print("uuid(%d): %d ms, hash: %s", COUNT, t * 1000, h) end -function test_random32() +function test_rand32() local h local n = COUNT / 10 local t = os.mclock() for i = 1, n do - h = hash.random32() + h = hash.rand32() end t = os.mclock() - t - print("random32(%d): %d ms, hash: %s", COUNT, t * 10, h) + print("rand32(%d): %d ms, hash: %s", COUNT, t * 10, h) end -function test_random64() +function test_rand64() local h local n = COUNT / 10 local t = os.mclock() for i = 1, n do - h = hash.random64() + h = hash.rand64() end t = os.mclock() - t - print("random64(%d): %d ms, hash: %s", COUNT, t * 10, h) + print("rand64(%d): %d ms, hash: %s", COUNT, t * 10, h) end -function test_random128() +function test_rand128() local h local n = COUNT / 10 local t = os.mclock() for i = 1, n do - h = hash.random128() + h = hash.rand128() end t = os.mclock() - t - print("random128(%d): %d ms, hash: %s", COUNT, t * 10, h) + print("rand128(%d): %d ms, hash: %s", COUNT, t * 10, h) end function test_longstr() @@ -202,9 +202,9 @@ end function test_random() print("========================================== test random ==========================================") test_random_uuid() - test_random32() - test_random64() - test_random128() + test_rand32() + test_rand64() + test_rand128() end function main() diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index 5f162af65..b4b42371d 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -136,31 +136,5 @@ function hash.strhash128(str) return hash._xxhash(128, data, size) end --- init random seed -function hash._init_random_seed() - if hash._INIT_RANDOM_SEED == nil then - math.randomseed(os.time()) - hash._INIT_RANDOM_SEED = true - end -end - --- generate random32 hash -function hash.random32() - return hash.strhash32(tostring(math.random())) -end - --- generate random64 hash -function hash.random64() - return hash.strhash64(tostring(math.random())) -end - --- generate random128 hash -function hash.random128() - return hash.strhash128(tostring(math.random())) -end - --- init random seed first -hash._init_random_seed() - -- return module: hash return hash diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 72d395d77..988d9e4bf 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -761,7 +761,7 @@ function os.tmpfile(opt_or_key) key = opt_or_key.key opt = opt_or_key end - local filename = "_" .. (key and hash.strhash128(key) or (hash.random128())) + local filename = "_" .. (key and hash.strhash128(key) or (hash.rand128())) return path.join(os.tmpdir(opt), filename) end diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 0f3a83bda..5af05c21f 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1381,7 +1381,7 @@ function project.tmpfile(opt_or_key) key = opt_or_key.key opt = opt_or_key end - local filename = "_" .. (key and hash.strhash128(key) or (hash.random128())) + local filename = "_" .. (key and hash.strhash128(key) or (hash.rand128())) return path.join(project.tmpdir(opt), "_" .. filename) end diff --git a/xmake/core/sandbox/modules/hash.lua b/xmake/core/sandbox/modules/hash.lua index 178bb2a5f..b5927b029 100644 --- a/xmake/core/sandbox/modules/hash.lua +++ b/xmake/core/sandbox/modules/hash.lua @@ -125,8 +125,8 @@ function sandbox_hash.strhash128(str) end -- generate random32 -function sandbox_hash.random32() - local result, errors = hash.random32() +function sandbox_hash.rand32() + local result, errors = hash.rand32() if not result then raise("cannot generate random32, %s", errors or "unknown errors") end @@ -134,8 +134,8 @@ function sandbox_hash.random32() end -- generate random64 -function sandbox_hash.random64() - local result, errors = hash.random64() +function sandbox_hash.rand64() + local result, errors = hash.rand64() if not result then raise("cannot generate random64, %s", errors or "unknown errors") end @@ -143,8 +143,8 @@ function sandbox_hash.random64() end -- generate random128 -function sandbox_hash.random128() - local result, errors = hash.random128() +function sandbox_hash.rand128() + local result, errors = hash.rand128() if not result then raise("cannot generate random128, %s", errors or "unknown errors") end -- cgit v1.3.1 From df4f8d13e506861cd6d9d8677cd270bfd0cd3a7b Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:49:02 +0800 Subject: update clock seed --- core/src/xmake/hash/rand128.c | 4 ++-- core/src/xmake/hash/rand32.c | 2 +- core/src/xmake/hash/rand64.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/xmake/hash/rand128.c b/core/src/xmake/hash/rand128.c index 946d396fd..1e1f34fde 100644 --- a/core/src/xmake/hash/rand128.c +++ b/core/src/xmake/hash/rand128.c @@ -41,8 +41,8 @@ tb_int_t xm_hash_rand128(lua_State* lua) 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_mclock(); - s_seed.word[1] = (tb_uint64_t)tb_mclock(); + 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); diff --git a/core/src/xmake/hash/rand32.c b/core/src/xmake/hash/rand32.c index b76b0ae15..66885a2cd 100644 --- a/core/src/xmake/hash/rand32.c +++ b/core/src/xmake/hash/rand32.c @@ -40,7 +40,7 @@ tb_int_t xm_hash_rand32(lua_State* lua) static union { tb_byte_t b[4]; tb_uint32_t word; } s_seed = {0}; if (!s_seed.word) - s_seed.word = (tb_uint32_t)tb_mclock(); + s_seed.word = (tb_uint32_t)tb_uclock(); s_seed.word = xm_hash_xorshift32(s_seed.word); tb_char_t s[64]; diff --git a/core/src/xmake/hash/rand64.c b/core/src/xmake/hash/rand64.c index a42d0eedb..31732bc53 100644 --- a/core/src/xmake/hash/rand64.c +++ b/core/src/xmake/hash/rand64.c @@ -40,7 +40,7 @@ tb_int_t xm_hash_rand64(lua_State* lua) 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_mclock(); + s_seed.word = (tb_uint64_t)tb_uclock(); s_seed.word = xm_hash_xorshift64(s_seed.word); tb_char_t s[256]; -- cgit v1.3.1 From 21c498ab682b083a58dbe25a716ba72a5012f8be Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:51:18 +0800 Subject: fix hash api --- xmake/plugins/project/cmake/cmakelists.lua | 4 ++-- xmake/rules/c++/unity_build/unity_build.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index ee6493cde..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.random32() + 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.random32() + 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++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 1ced33ec8..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.random32()) + unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.rand32()) end unityfile:print("#include \"%s\"", sourcefile) if uniqueid then -- cgit v1.3.1 From 70db5d57333ce0b5f8a083b26be01d2a357d1133 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:53:49 +0800 Subject: fix compile error --- core/src/xmake/hash/rand32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/hash/rand32.c b/core/src/xmake/hash/rand32.c index 66885a2cd..c14c6288e 100644 --- a/core/src/xmake/hash/rand32.c +++ b/core/src/xmake/hash/rand32.c @@ -43,7 +43,7 @@ tb_int_t xm_hash_rand32(lua_State* lua) s_seed.word = (tb_uint32_t)tb_uclock(); s_seed.word = xm_hash_xorshift32(s_seed.word); - tb_char_t s[64]; + tb_char_t s[256]; tb_size_t n = xm_hash_make_cstr(s, s_seed.b, 4); lua_pushlstring(lua, s, n); -- cgit v1.3.1 From 0046d446d0f3f31cb1a89081ca5841b79918f904 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Oct 2025 00:58:11 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index b4c7e09b7..46f5987ad 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit b4c7e09b76751eacb7afa1521ac688e54b9cc767 +Subproject commit 46f5987ad31f4a52ee99417d62196f9bb524835c -- cgit v1.3.1 From 0938e19d1ff2711224c6e8675366fed845b28c0d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Oct 2025 00:42:11 +0800 Subject: support old core --- xmake/core/base/hash.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index b4b42371d..f08c562aa 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -31,6 +31,9 @@ local libc = require("base/libc") 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) @@ -136,5 +139,32 @@ function hash.strhash128(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 return hash -- cgit v1.3.1 From 6377f4494967e341150f0e2bb042d3c7d8bd15c9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Oct 2025 22:50:18 +0800 Subject: improve rand32 --- core/src/xmake/hash/prefix.h | 8 -------- core/src/xmake/hash/rand32.c | 11 ++++++----- core/src/xmake/hash/xxhash.c | 36 +++++++++++++++++++++++++----------- xmake/core/base/hash.lua | 18 +++++++++--------- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/core/src/xmake/hash/prefix.h b/core/src/xmake/hash/prefix.h index 59a3941d7..8a321e1eb 100644 --- a/core/src/xmake/hash/prefix.h +++ b/core/src/xmake/hash/prefix.h @@ -30,14 +30,6 @@ * helper implementation */ -static __tb_inline__ tb_uint32_t xm_hash_xorshift32(tb_uint32_t x) -{ - x ^= x << 13; - x ^= x >> 7; - x ^= x << 17; - return x; -} - static __tb_inline__ tb_uint64_t xm_hash_xorshift64(tb_uint64_t x) { x ^= x << 13; diff --git a/core/src/xmake/hash/rand32.c b/core/src/xmake/hash/rand32.c index c14c6288e..bbf565acd 100644 --- a/core/src/xmake/hash/rand32.c +++ b/core/src/xmake/hash/rand32.c @@ -38,13 +38,14 @@ tb_int_t xm_hash_rand32(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - static union { tb_byte_t b[4]; tb_uint32_t word; } s_seed = {0}; - if (!s_seed.word) - s_seed.word = (tb_uint32_t)tb_uclock(); - s_seed.word = xm_hash_xorshift32(s_seed.word); + 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_size_t n = xm_hash_make_cstr(s, s_seed.b, 4); + 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/xxhash.c b/core/src/xmake/hash/xxhash.c index 0c9dbdad7..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) { @@ -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,17 +148,24 @@ 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 diff --git a/xmake/core/base/hash.lua b/xmake/core/base/hash.lua index f08c562aa..e846ba302 100644 --- a/xmake/core/base/hash.lua +++ b/xmake/core/base/hash.lua @@ -81,11 +81,15 @@ end -- generate xxhash32 from the given file or data function hash.xxhash32(file_or_data) - local result, errors = hash.xxhash64(file_or_data) - if result then - result = result:sub(1, 8) + 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 result, errors + return hashstr, errors end -- generate xxhash64 from the given file or data @@ -118,11 +122,7 @@ end function hash.strhash32(str) local data = libc.ptraddr(libc.dataptr(str)) local size = #str - local result, errors = hash._xxhash(64, data, size) - if result then - result = result:sub(1, 8) - end - return result, errors + return hash._xxhash(32, data, size) end -- generate hash64 from string, e.g. "91e8ecf191e8ecf1" -- cgit v1.3.1