diff options
| author | ruki <[email protected]> | 2025-10-01 00:47:56 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-10-01 00:47:56 +0800 |
| commit | 9dc8bb99439f4d31e3563a5865764798c2094e8e (patch) | |
| tree | 911e222e99d1df86804f1380940f829045fbe97b | |
| parent | 672470e6e4ea7fd150354c131ba5fb60f7331643 (diff) | |
improve random hash
| -rw-r--r-- | core/src/xmake/engine.c | 16 | ||||
| -rw-r--r-- | core/src/xmake/hash/prefix.h | 27 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand128.c | 55 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand32.c | 51 | ||||
| -rw-r--r-- | core/src/xmake/hash/rand64.c | 51 | ||||
| -rw-r--r-- | tests/benchmarks/hash.lua | 24 | ||||
| -rw-r--r-- | xmake/core/base/hash.lua | 26 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 2 | ||||
| -rw-r--r-- | xmake/core/project/project.lua | 2 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/hash.lua | 12 |
10 files changed, 215 insertions, 51 deletions
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 |
