diff --git a/PHP/README.md b/PHP/README.md index 794c71a..2bbb70c 100644 --- a/PHP/README.md +++ b/PHP/README.md @@ -23,14 +23,14 @@ make install **配置文件配置参数**: ```shell //snowdrift.ini -snowdrift.Method=1 //1 漂移算法 2 传统算法 -snowdrift.BaseTime=1582136402000 -snowdrift.WorkerId=1 //默认workerid,支持参数传递改变实际使用的值,范围1~(-1L << snowdrift.WorkerIdBitLength) ^ -1L -snowdrift.WorkerIdBitLength=6 //WorkerId位数,默认6。 -snowdrift.SeqBitLength=6 //自增序号位数 -snowdrift.MaxSeqNumber=0 //默认值为0,0时自动计算=(-1L << snowdrift.SeqBitLength) ^ -1L,需大于MinSeqNumber -snowdrift.MinSeqNumber=5 //默认值为5,当配置了MaxSeqNumber时,需小于MaxSeqNumber -snowdrift.TopOverCostCount=2000 //最大漂移次数 +snowdrift.Method=1 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 +snowdrift.BaseTime=1582136402000 //基础时间(ms单位),不能超过当前系统时间 +snowdrift.WorkerId=1 //机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1 +snowdrift.WorkerIdBitLength=6 //机器码位长,默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) +snowdrift.SeqBitLength=6 //序列数位长,默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) +snowdrift.MaxSeqNumber=0 //最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1] +snowdrift.MinSeqNumber=5 //最小序列数(含),默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 +snowdrift.TopOverCostCount=2000 //最大漂移次数(含),默认2000,推荐范围 500-20000(与计算能力有关) ``` **函数签名**: diff --git a/PHP/snowdrift.c b/PHP/snowdrift.c index 628c56a..4ea4e32 100644 --- a/PHP/snowdrift.c +++ b/PHP/snowdrift.c @@ -99,8 +99,6 @@ PHP_METHOD(snowdrift, NextId) RETURN_LONG(NextId(flake)); } -/** 这种方式性能比不上PHP直接循环调用NextId快 - */ PHP_METHOD(snowdrift, NextNumId) { zend_long num = 1; diff --git a/PHP/src/snowflake/snowflake.c b/PHP/src/snowflake/snowflake.c index feebd45..2db5555 100644 --- a/PHP/src/snowflake/snowflake.c +++ b/PHP/src/snowflake/snowflake.c @@ -9,12 +9,13 @@ #endif static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake); -static uint64_t NextOverCostId(snowflake *flake); -static uint64_t NextNormalId(snowflake *flake); -static uint64_t GetCurrentTimeTick(snowflake *flake); -static uint64_t GetNextTimeTick(snowflake *flake); -static uint64_t CalcId(snowflake *flake); -static uint64_t CalcTurnBackId(snowflake *flake); +static inline uint64_t NextOverCostId(snowflake *flake); +static inline uint64_t NextNormalId(snowflake *flake); +static inline uint64_t GetCurrentTimeTick(snowflake *flake); +static inline uint64_t GetNextTimeTick(snowflake *flake); +static inline uint64_t CalcId(snowflake *flake); +static inline uint64_t CalcTurnBackId(snowflake *flake); +static inline uint64_t GetCurrentTime(); int ncpu; uint16_t spin = 2048; @@ -37,19 +38,90 @@ void Config(snowflake *flake) ncpu = 1; } } - flake->WorkerIdBitLength = flake->WorkerIdBitLength == 0 ? 6 : flake->WorkerIdBitLength; - flake->SeqBitLength = flake->SeqBitLength == 0 ? 6 : flake->SeqBitLength; - flake->MaxSeqNumber = flake->MaxSeqNumber > 0 ? flake->MaxSeqNumber : (-1L << flake->SeqBitLength) ^ -1L; - flake->BaseTime = flake->BaseTime != 0 ? flake->BaseTime : 1577808000000; - flake->_TimestampShift = (uint8_t)(flake->WorkerIdBitLength + flake->SeqBitLength); - flake->_CurrentSeqNumber = flake->MinSeqNumber; - if (flake->MaxSeqNumber <= flake->MinSeqNumber) + if (flake->BaseTime == 0) + { + flake->BaseTime = 1582136402000; + } + else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetCurrentTime()) + { + perror("BaseTime error."); + return 0; + } + + // 2.WorkerIdBitLength + if (flake->WorkerIdBitLength <= 0) + { + perror("WorkerIdBitLength error.(range:[1, 21])"); + exit(1); + } + if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) + { + perror("error:WorkerIdBitLength + SeqBitLength <= 22"); + exit(1); + } + else { - flake->MinSeqNumber = 0; + flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; } + + // 3.WorkerId + uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; + if (maxWorkerIdNumber == 0) + { + maxWorkerIdNumber = 63; + } + if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) + { + perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); + exit(1); + } + + // 4.SeqBitLength + if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) + { + perror("SeqBitLength error. (range:[2, 21])"); + exit(1); + } + else + { + flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; + } + + // 5.MaxSeqNumber + uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; + if (maxSeqNumber == 0) + { + maxSeqNumber = 63; + } + if (flake->MaxSeqNumber > maxSeqNumber) + { + perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); + exit(1); + } + else + { + flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; + } + + // 6.MinSeqNumber + if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) + { + perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); + exit(1); + } + else + { + flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; + } + + // 7.Others + flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; + flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; + flake->_CurrentSeqNumber = flake->MinSeqNumber; + flake->Method = flake->Method; } -void inline EndOverCostAction(uint64_t useTimeTick, snowflake *flake) +static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake) { if (flake->_TermIndex > 10000) { @@ -57,7 +129,7 @@ void inline EndOverCostAction(uint64_t useTimeTick, snowflake *flake) } } -uint64_t inline NextOverCostId(snowflake *flake) +static inline uint64_t NextOverCostId(snowflake *flake) { uint64_t currentTimeTick = GetCurrentTimeTick(flake); if (currentTimeTick > flake->_LastTimeTick) @@ -94,7 +166,7 @@ uint64_t inline NextOverCostId(snowflake *flake) return CalcId(flake); } -uint64_t inline NextNormalId(snowflake *flake) +static inline uint64_t NextNormalId(snowflake *flake) { uint64_t currentTimeTick = GetCurrentTimeTick(flake); if (currentTimeTick < flake->_LastTimeTick) @@ -133,14 +205,19 @@ uint64_t inline NextNormalId(snowflake *flake) return CalcId(flake); } -uint64_t inline GetCurrentTimeTick(snowflake *flake) +static inline uint64_t GetCurrentTime() { struct timeval t; gettimeofday(&t, NULL); - return (uint64_t)((t.tv_sec * 1000 + t.tv_usec / 1000) - flake->BaseTime); + return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); +} + +static inline uint64_t GetCurrentTimeTick(snowflake *flake) +{ + return GetCurrentTime() - flake->BaseTime; } -uint64_t inline GetNextTimeTick(snowflake *flake) +static inline uint64_t GetNextTimeTick(snowflake *flake) { uint64_t tempTimeTicker = GetCurrentTimeTick(flake); while (tempTimeTicker <= flake->_LastTimeTick) @@ -150,21 +227,21 @@ uint64_t inline GetNextTimeTick(snowflake *flake) return tempTimeTicker; } -uint64_t inline CalcId(snowflake *flake) +static inline uint64_t CalcId(snowflake *flake) { uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); flake->_CurrentSeqNumber++; return result; } -uint64_t inline CalcTurnBackId(snowflake *flake) +static inline uint64_t CalcTurnBackId(snowflake *flake) { uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); flake->_TurnBackTimeTick--; return result; } -uint64_t inline NextSonwId(snowflake *flake) +static inline uint64_t NextSonwId(snowflake *flake) { uint64_t currentTimeTick = GetCurrentTimeTick(flake); if (flake->_LastTimeTick == currentTimeTick) @@ -184,7 +261,7 @@ uint64_t inline NextSonwId(snowflake *flake) return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); } -uint64_t inline GetId(snowflake *flake) +static inline uint64_t GetId(snowflake *flake) { return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); } diff --git a/PHP/src/test.c b/PHP/src/test.c index 533bf94..fd5856a 100644 --- a/PHP/src/test.c +++ b/PHP/src/test.c @@ -12,7 +12,7 @@ #define THREAD 2 #define TOTAL 50000 -static snowflake snowf = {1, 0, 1, 6, 6, 0, 0, 2000}; +static snowflake snowf = {1, 0, 1, 6, 12, 0, 5, 2000}; static snowflake *flake = &snowf; uint64_t arr[TOTAL]; diff --git a/zzz-OtherLanguages/V/source/contract/IdGeneratorOptions.v b/zzz-OtherLanguages/V/source/contract/IdGeneratorOptions.v index a7da5bd..bafe4a5 100644 --- a/zzz-OtherLanguages/V/source/contract/IdGeneratorOptions.v +++ b/zzz-OtherLanguages/V/source/contract/IdGeneratorOptions.v @@ -4,10 +4,10 @@ pub struct IdGeneratorOptions { pub mut: method u16 = 1 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 base_time i64 = 1582136402000 // 基础时间,不能超过当前系统时间 - worker_id u16 = 1 // 机器码,与 workerid_bitlength 有关系 - workerid_bitlength byte = 6 // 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) - seq_bitlength byte = 6 // 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) - max_seqnumber u32 = 0 // 最大序列数(含),(由seq_bitlength计算的最大值) - min_seqnumber u32 = 5 // 最小序列数(含),默认5,不小于1,不大于max_seqnumber - top_over_cost_count u32 = 2000 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) + worker_id u16 = 1 // 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1 + workerid_bitlength byte = 6 // 机器码位长,默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) + seq_bitlength byte = 6 // 序列数位长,默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) + max_seqnumber u32 = 0 // 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1]) + min_seqnumber u32 = 5 // 最小序列数(含),默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 + top_over_cost_count u32 = 2000 // 最大漂移次数(含),默认2000,推荐范围 500-20000(与计算能力有关) }