| @@ -12,7 +12,7 @@ namespace Yitter.OrgSystem.TestA | |||
| class Program | |||
| { | |||
| // 测试参数(默认配置下,最佳性能是10W/s) | |||
| static int genIdCount = 500000;//5000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为2000或适当增加SeqBitLength) | |||
| static int genIdCount = 50000;//5000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为2000或适当增加SeqBitLength) | |||
| static short method = 1; // 1-漂移算法,2-传统算法 | |||
| @@ -39,7 +39,7 @@ namespace Yitter.OrgSystem.TestA | |||
| WorkerIdBitLength = 6, | |||
| SeqBitLength = 6, | |||
| DataCenterIdBitLength = 10, | |||
| DataCenterIdBitLength = 0, | |||
| TopOverCostCount = 2000, | |||
| //TimestampType = 1, | |||
| @@ -142,8 +142,8 @@ namespace Yitter.OrgSystem.TestA | |||
| //WorkerIdBitLength = 6, | |||
| SeqBitLength = 6, | |||
| //DataCenterIdBitLength = 0, | |||
| //TopOverCostCount = 2000, | |||
| //DataCenterIdBitLength = 0, | |||
| //TimestampType = 1, | |||
| // MinSeqNumber = 1, | |||
| @@ -63,7 +63,6 @@ namespace Yitter.IdGenerator | |||
| /// </summary> | |||
| public virtual int TopOverCostCount { get; set; } = 2000; | |||
| /// <summary> | |||
| /// 数据中心ID(默认0) | |||
| /// </summary> | |||
| @@ -118,10 +118,10 @@ namespace Yitter.IdGenerator | |||
| // 7.Others | |||
| TopOverCostCount = options.TopOverCostCount; | |||
| if (TopOverCostCount == 0) | |||
| { | |||
| TopOverCostCount = 2000; | |||
| } | |||
| //if (TopOverCostCount == 0) | |||
| //{ | |||
| // TopOverCostCount = 2000; | |||
| //} | |||
| _TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); | |||
| _CurrentSeqNumber = options.MinSeqNumber; | |||
| @@ -92,6 +92,12 @@ namespace Yitter.IdGenerator | |||
| throw new ApplicationException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | |||
| } | |||
| // 7.TopOverCostCount | |||
| if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) | |||
| { | |||
| throw new ApplicationException("TopOverCostCount error. (range:[0, 10000]"); | |||
| } | |||
| switch (options.Method) | |||
| { | |||
| case 2: | |||
| @@ -9,107 +9,147 @@ | |||
| #include <unistd.h> | |||
| #include "IdGenerator.h" | |||
| static inline uint64_t WorkerM1Id() { | |||
| static inline uint64_t WorkerM1Id() | |||
| { | |||
| return WorkerM1NextId(_idGenerator->Worker); | |||
| } | |||
| static inline uint64_t WorkerM2Id() { | |||
| static inline uint64_t WorkerM2Id() | |||
| { | |||
| return WorkerM2NextId(_idGenerator->Worker); | |||
| } | |||
| extern IdGenerator *GetIdGenInstance() { | |||
| extern IdGenerator *GetIdGenInstance() | |||
| { | |||
| if (_idGenerator != NULL) | |||
| return _idGenerator; | |||
| else { | |||
| _idGenerator = (IdGenerator *) malloc(sizeof(IdGenerator)); | |||
| else | |||
| { | |||
| _idGenerator = (IdGenerator *)malloc(sizeof(IdGenerator)); | |||
| _idGenerator->Worker = NewSnowFlakeWorker(); | |||
| return _idGenerator; | |||
| } | |||
| } | |||
| extern void SetOptions(IdGeneratorOptions options) { | |||
| if (GetIdGenInstance() == NULL) { | |||
| extern void SetOptions(IdGeneratorOptions options) | |||
| { | |||
| if (GetIdGenInstance() == NULL) | |||
| { | |||
| exit(1); | |||
| } | |||
| // 1.BaseTime | |||
| if (options.BaseTime == 0) { | |||
| if (options.BaseTime == 0) | |||
| { | |||
| _idGenerator->Worker->BaseTime = 1582136402000; | |||
| } else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) { | |||
| } | |||
| else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) | |||
| { | |||
| perror("BaseTime error."); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| _idGenerator->Worker->BaseTime = options.BaseTime; | |||
| } | |||
| // 2.WorkerIdBitLength | |||
| if (options.WorkerIdBitLength <= 0) { | |||
| if (options.WorkerIdBitLength <= 0) | |||
| { | |||
| perror("WorkerIdBitLength error.(range:[1, 21])"); | |||
| exit(1); | |||
| } | |||
| if (options.SeqBitLength + options.WorkerIdBitLength > 22) { | |||
| if (options.SeqBitLength + options.WorkerIdBitLength > 22) | |||
| { | |||
| perror("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| // _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength; | |||
| _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength <= 0 ? 6 : options.WorkerIdBitLength; | |||
| } | |||
| // 3.WorkerId | |||
| uint32_t maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; | |||
| if (maxWorkerIdNumber == 0) { | |||
| if (maxWorkerIdNumber == 0) | |||
| { | |||
| maxWorkerIdNumber = 63; | |||
| } | |||
| if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { | |||
| if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) | |||
| { | |||
| perror("WorkerId error. (range:[0, {2^options.WorkerIdBitLength-1]}"); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| _idGenerator->Worker->WorkerId = options.WorkerId; | |||
| } | |||
| // 4.SeqBitLength | |||
| if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { | |||
| if (options.SeqBitLength < 2 || options.SeqBitLength > 21) | |||
| { | |||
| perror("SeqBitLength error. (range:[2, 21])"); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| // _idGenerator->Worker->SeqBitLength = options.SeqBitLength; | |||
| _idGenerator->Worker->SeqBitLength = options.SeqBitLength <= 0 ? 6 : options.SeqBitLength; | |||
| } | |||
| // 5.MaxSeqNumber | |||
| uint32_t maxSeqNumber = (1 << options.SeqBitLength) - 1; | |||
| if (maxSeqNumber == 0) { | |||
| if (maxSeqNumber == 0) | |||
| { | |||
| maxSeqNumber = 63; | |||
| } | |||
| if (options.MaxSeqNumber > maxSeqNumber) { | |||
| if (options.MaxSeqNumber > maxSeqNumber) | |||
| { | |||
| perror("MaxSeqNumber error. (range:[1, {2^options.SeqBitLength-1}]"); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| _idGenerator->Worker->MaxSeqNumber = options.MaxSeqNumber <= 0 ? maxSeqNumber : options.MaxSeqNumber; | |||
| } | |||
| // 6.MinSeqNumber | |||
| if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) { | |||
| if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) | |||
| { | |||
| perror("MinSeqNumber error. (range:[5, {options.MinSeqNumber}]"); | |||
| exit(1); | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| _idGenerator->Worker->MinSeqNumber = options.MinSeqNumber <= 0 ? 5 : options.MinSeqNumber; | |||
| } | |||
| // 7.Others | |||
| _idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; | |||
| // 7.TopOverCostCount | |||
| if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) | |||
| { | |||
| perror("TopOverCostCount error. (range:[0, 10000]"); | |||
| exit(1); | |||
| } | |||
| else | |||
| { | |||
| //_idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; | |||
| _idGenerator->Worker->TopOverCostCount = options.TopOverCostCount; | |||
| } | |||
| // 8.Others | |||
| _idGenerator->Worker->_TimestampShift = | |||
| _idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; | |||
| _idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; | |||
| _idGenerator->Worker->_CurrentSeqNumber = _idGenerator->Worker->MinSeqNumber; | |||
| _idGenerator->Worker->Method = options.Method; | |||
| if (options.Method == 2) { | |||
| if (options.Method == 2) | |||
| { | |||
| _idGenerator->NextId = WorkerM2Id; | |||
| } else { | |||
| } | |||
| else | |||
| { | |||
| _idGenerator->NextId = WorkerM1Id; | |||
| usleep(500*1000); // 暂停500ms | |||
| usleep(500 * 1000); // 暂停500ms | |||
| } | |||
| } | |||
| @@ -4,6 +4,7 @@ | |||
| * 代码修订:yitter | |||
| * 开源地址:https://github.com/yitter/idgenerator | |||
| */ | |||
| package idgen | |||
| import ( | |||
| @@ -64,6 +65,11 @@ func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { | |||
| panic("MinSeqNumber error. (range:[5, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") | |||
| } | |||
| // 7.TopOverCostCount | |||
| if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { | |||
| panic("TopOverCostCount error. (range:[0, 10000]") | |||
| } | |||
| var snowWorker ISnowWorker | |||
| switch options.Method { | |||
| case 1: | |||
| @@ -4,6 +4,7 @@ | |||
| * 代码修订:yitter | |||
| * 开源地址:https://github.com/yitter/idgenerator | |||
| */ | |||
| package idgen | |||
| import ( | |||
| @@ -13,13 +14,13 @@ import ( | |||
| // SnowWorkerM1 . | |||
| type SnowWorkerM1 struct { | |||
| BaseTime int64 //基础时间 | |||
| WorkerId uint16 //机器码 | |||
| WorkerIdBitLength byte //机器码位长 | |||
| SeqBitLength byte //自增序列数位长 | |||
| MaxSeqNumber uint32 //最大序列数(含) | |||
| MinSeqNumber uint32 //最小序列数(含) | |||
| TopOverCostCount uint32 //最大漂移次数 | |||
| BaseTime int64 // 基础时间 | |||
| WorkerId uint16 // 机器码 | |||
| WorkerIdBitLength byte // 机器码位长 | |||
| SeqBitLength byte // 自增序列数位长 | |||
| MaxSeqNumber uint32 // 最大序列数(含) | |||
| MinSeqNumber uint32 // 最小序列数(含) | |||
| TopOverCostCount uint32 // 最大漂移次数 | |||
| _TimestampShift byte | |||
| _CurrentSeqNumber uint32 | |||
| @@ -75,12 +76,13 @@ func NewSnowWorkerM1(options *IdGeneratorOptions) ISnowWorker { | |||
| // 6.MinSeqNumber | |||
| var minSeqNumber = options.MinSeqNumber | |||
| // 7.Others | |||
| // 7.TopOverCostCount | |||
| var topOverCostCount = options.TopOverCostCount | |||
| if topOverCostCount == 0 { | |||
| topOverCostCount = 2000 | |||
| } | |||
| // if topOverCostCount == 0 { | |||
| // topOverCostCount = 2000 | |||
| // } | |||
| // 8.Others | |||
| timestampShift := (byte)(workerIdBitLength + seqBitLength) | |||
| currentSeqNumber := minSeqNumber | |||
| @@ -66,7 +66,8 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
| SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; | |||
| MaxSeqNumber = options.MaxSeqNumber <= 0 ? (1 << SeqBitLength) - 1 : options.MaxSeqNumber; | |||
| MinSeqNumber = options.MinSeqNumber; | |||
| TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; | |||
| // TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; | |||
| TopOverCostCount = options.TopOverCostCount; | |||
| _TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); | |||
| _CurrentSeqNumber = MinSeqNumber; | |||
| } | |||
| @@ -150,11 +151,11 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
| BeginTurnBackAction(_TurnBackTimeTick); | |||
| } | |||
| // try { | |||
| // Thread.sleep(1); | |||
| // } catch (InterruptedException e) { | |||
| // e.printStackTrace(); | |||
| // } | |||
| // try { | |||
| // Thread.sleep(1); | |||
| // } catch (InterruptedException e) { | |||
| // e.printStackTrace(); | |||
| // } | |||
| return CalcTurnBackId(_TurnBackTimeTick); | |||
| } | |||
| @@ -214,7 +215,7 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
| long tempTimeTicker = GetCurrentTimeTick(); | |||
| while (tempTimeTicker <= _LastTimeTick) { | |||
| try { | |||
| try { | |||
| Thread.sleep(1); | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| @@ -232,4 +233,3 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
| } | |||
| } | |||
| } | |||
| @@ -11,7 +11,6 @@ import com.github.yitter.contract.IdGeneratorOptions; | |||
| import com.github.yitter.core.SnowWorkerM1; | |||
| import com.github.yitter.core.SnowWorkerM2; | |||
| public class DefaultIdGenerator implements IIdGenerator { | |||
| private static ISnowWorker _SnowWorker = null; | |||
| @@ -40,7 +39,8 @@ public class DefaultIdGenerator implements IIdGenerator { | |||
| maxWorkerIdNumber = 63; | |||
| } | |||
| if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { | |||
| throw new IdGeneratorException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); | |||
| throw new IdGeneratorException( | |||
| "WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); | |||
| } | |||
| // 4.SeqBitLength | |||
| @@ -62,6 +62,11 @@ public class DefaultIdGenerator implements IIdGenerator { | |||
| throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | |||
| } | |||
| // 7.TopOverCostCount | |||
| if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) { | |||
| throw new IdGeneratorException("TopOverCostCount error. (range:[0, 10000]"); | |||
| } | |||
| switch (options.Method) { | |||
| case 2: | |||
| _SnowWorker = new SnowWorkerM2(options); | |||
| @@ -26,7 +26,7 @@ public class GenTest { | |||
| long end = System.currentTimeMillis(); | |||
| long time = end - start; | |||
| System.out.println(id); | |||
| // System.out.println(id); | |||
| System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " | |||
| + WorkerId + ", total: " + time + " ms"); | |||
| @@ -25,7 +25,7 @@ public class StartUp { | |||
| // options.BaseTime = 1582206693000L; | |||
| options.Method = method; | |||
| options.WorkerId = 1; | |||
| options.TopOverCostCount=2000; | |||
| // options.TopOverCostCount=2000; | |||
| // 首先测试一下 IdHelper 方法,获取单个Id | |||
| YitIdHelper.setIdGenerator(options); | |||
| @@ -39,7 +39,7 @@ public class StartUp { | |||
| while (true) { | |||
| genTest.GenStart(); | |||
| Thread.sleep(1000); // 每隔1秒执行一次GenStart | |||
| System.out.println("Hello World! Java"); | |||
| // System.out.println("Hello World! Java"); | |||
| } | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| @@ -2,10 +2,10 @@ | |||
| * 版权属于:yitter(yitter@126.com) | |||
| * 开源地址:https://github.com/yitter/idgenerator | |||
| */ | |||
| use std::{thread}; | |||
| use crate::idgen::*; | |||
| use chrono::Utc; | |||
| use std::thread; | |||
| use std::thread::sleep; | |||
| use crate::idgen::*; | |||
| // use lazy_static::lazy_static; | |||
| pub struct SnowWorkerM1 { | |||
| @@ -42,26 +42,30 @@ impl SnowWorkerM1 { | |||
| } | |||
| pub fn SetOptions(&mut self, options: IdGeneratorOptions) { | |||
| // 1.BaseTime | |||
| if options.BaseTime == 0 { | |||
| self.BaseTime = 1582136402000; | |||
| } else if options.BaseTime < 631123200000 || options.BaseTime > Utc::now().timestamp_millis() { | |||
| } else if options.BaseTime < 631123200000 | |||
| || options.BaseTime > Utc::now().timestamp_millis() | |||
| { | |||
| panic!("BaseTime error."); | |||
| } else { | |||
| self.BaseTime = options.BaseTime; | |||
| } | |||
| // 2.WorkerIdBitLength | |||
| if options.WorkerIdBitLength <= 0 | |||
| { | |||
| if options.WorkerIdBitLength <= 0 { | |||
| panic!("WorkerIdBitLength error.(range:[1, 21])"); | |||
| } | |||
| if options.SeqBitLength + options.WorkerIdBitLength > 22 { | |||
| panic!("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||
| } else { | |||
| // self.WorkerIdBitLength = options.WorkerIdBitLength; | |||
| self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { 6 } else { options.WorkerIdBitLength }; | |||
| self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { | |||
| 6 | |||
| } else { | |||
| options.WorkerIdBitLength | |||
| }; | |||
| } | |||
| // 3.WorkerId | |||
| @@ -80,7 +84,11 @@ impl SnowWorkerM1 { | |||
| panic!("SeqBitLength error. (range:[2, 21])"); | |||
| } else { | |||
| // self.SeqBitLength = options.SeqBitLength; | |||
| self.SeqBitLength = if options.SeqBitLength <= 0 { 6 } else { options.SeqBitLength }; | |||
| self.SeqBitLength = if options.SeqBitLength <= 0 { | |||
| 6 | |||
| } else { | |||
| options.SeqBitLength | |||
| }; | |||
| } | |||
| // 5.MaxSeqNumber | |||
| @@ -91,7 +99,11 @@ impl SnowWorkerM1 { | |||
| if options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber { | |||
| panic!("MaxSeqNumber error. (range:[1, {}]", maxSeqNumber); | |||
| } else { | |||
| self.MaxSeqNumber = if options.MaxSeqNumber == 0 { maxSeqNumber } else { options.MaxSeqNumber }; | |||
| self.MaxSeqNumber = if options.MaxSeqNumber == 0 { | |||
| maxSeqNumber | |||
| } else { | |||
| options.MaxSeqNumber | |||
| }; | |||
| } | |||
| // 6.MinSeqNumber | |||
| @@ -102,8 +114,15 @@ impl SnowWorkerM1 { | |||
| // self.MinSeqNumber = if options.MinSeqNumber <= 0 { 5 } else { options.MinSeqNumber }; | |||
| } | |||
| // 7.Others | |||
| self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; | |||
| // 7.TopOverCostCount | |||
| //self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; | |||
| if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { | |||
| panic!("TopOverCostCount error. (range:[0, 10000]"); | |||
| } else { | |||
| self.TopOverCostCount = options.TopOverCostCount; | |||
| } | |||
| // 8.Others | |||
| self._TimestampShift = self.WorkerIdBitLength + self.SeqBitLength; | |||
| self._CurrentSeqNumber = self.MinSeqNumber; | |||
| @@ -139,7 +158,11 @@ impl SnowWorkerM1 { | |||
| pub fn NextId(&mut self) -> i64 { | |||
| // println!("SeqBitLength: {}", self.SeqBitLength); | |||
| if self._IsOverCost { self.NextOverCostId() } else { self.NextNormalId() } | |||
| if self._IsOverCost { | |||
| self.NextOverCostId() | |||
| } else { | |||
| self.NextNormalId() | |||
| } | |||
| } | |||
| fn DoGenIdAction(&self, arg: OverCostActionArg) {} | |||
| @@ -247,17 +270,17 @@ impl SnowWorkerM1 { | |||
| } | |||
| fn CalcId(&mut self, useTimeTick: i64) -> i64 { | |||
| let result = (useTimeTick << self._TimestampShift) + | |||
| (self.WorkerId << self.SeqBitLength) as i64 + | |||
| (self._CurrentSeqNumber) as i64; | |||
| let result = (useTimeTick << self._TimestampShift) | |||
| + (self.WorkerId << self.SeqBitLength) as i64 | |||
| + (self._CurrentSeqNumber) as i64; | |||
| self._CurrentSeqNumber += 1; | |||
| return result; | |||
| } | |||
| fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { | |||
| let result = (useTimeTick << self._TimestampShift) + | |||
| (self.WorkerId << self.SeqBitLength) as i64 + | |||
| (self._TurnBackIndex) as i64; | |||
| let result = (useTimeTick << self._TimestampShift) | |||
| + (self.WorkerId << self.SeqBitLength) as i64 | |||
| + (self._TurnBackIndex) as i64; | |||
| self._TurnBackTimeTick -= 1; | |||
| return result; | |||
| } | |||
| @@ -277,4 +300,4 @@ impl SnowWorkerM1 { | |||
| return tempTimeTicker; | |||
| } | |||
| } | |||
| } | |||