From a82d9cb0638c23322cfcbd66fee32a24841fddd7 Mon Sep 17 00:00:00 2001 From: BitWorld Date: Thu, 8 Apr 2021 21:04:43 +0800 Subject: [PATCH] =?UTF-8?q?!6=20D=E8=AF=AD=E8=A8=80=E7=A7=BB=E6=A4=8D=20*?= =?UTF-8?q?=20Porting=20to=20D=20*=20The=20pthread=20needed.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 + C/source/CMakeLists.txt | 7 +- D/README.md | 32 +++ D/dub.json | 9 + D/source/yitter/contract/IIdGenerator.d | 9 + D/source/yitter/contract/ISnowWorker.d | 9 + .../yitter/contract/IdGeneratorException.d | 29 +++ D/source/yitter/contract/IdGeneratorOptions.d | 72 ++++++ D/source/yitter/contract/OverCostActionArg.d | 52 ++++ D/source/yitter/contract/package.d | 7 + D/source/yitter/core/SnowWorkerM1.d | 237 ++++++++++++++++++ D/source/yitter/core/SnowWorkerM2.d | 50 ++++ D/source/yitter/idgen/DefaultIdGenerator.d | 98 ++++++++ D/source/yitter/idgen/YitIdHelper.d | 43 ++++ D/source/yitter/package.d | 6 + D/test/dub.json | 14 ++ D/test/source/GenTest.d | 38 +++ D/test/source/app.d | 52 ++++ 18 files changed, 768 insertions(+), 3 deletions(-) create mode 100644 D/README.md create mode 100644 D/dub.json create mode 100644 D/source/yitter/contract/IIdGenerator.d create mode 100644 D/source/yitter/contract/ISnowWorker.d create mode 100644 D/source/yitter/contract/IdGeneratorException.d create mode 100644 D/source/yitter/contract/IdGeneratorOptions.d create mode 100644 D/source/yitter/contract/OverCostActionArg.d create mode 100644 D/source/yitter/contract/package.d create mode 100644 D/source/yitter/core/SnowWorkerM1.d create mode 100644 D/source/yitter/core/SnowWorkerM2.d create mode 100644 D/source/yitter/idgen/DefaultIdGenerator.d create mode 100644 D/source/yitter/idgen/YitIdHelper.d create mode 100644 D/source/yitter/package.d create mode 100644 D/test/dub.json create mode 100644 D/test/source/GenTest.d create mode 100644 D/test/source/app.d diff --git a/.gitignore b/.gitignore index 2f8cf8a..74c0dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -257,3 +257,10 @@ target/ # macOS .DS_Store +D/test/test +D/libyitterd.a +D/dub.*.json +*/.dub/* +*/test/.dub/* +C/source/build/* +D/test/dub.*.json diff --git a/C/source/CMakeLists.txt b/C/source/CMakeLists.txt index a72c2e7..38d8db8 100644 --- a/C/source/CMakeLists.txt +++ b/C/source/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.13) project(YitIdGen) set(CMAKE_C_STANDARD 11) @@ -8,6 +8,7 @@ set(CMAKE_C_STANDARD 11) aux_source_directory(. DIR_SRCS) add_subdirectory(idgen) + #编译动态库 #set(LIB_SRC YitIdHelper.h YitIdHelper.c) #add_library(YitIdGenLib SHARED ${LIB_SRC}) @@ -21,7 +22,7 @@ add_subdirectory(idgen) set(LIB_SRC YitIdHelper.h YitIdHelper.c) add_library(YitIdHelper ${LIB_SRC}) add_executable(YitIdGen main.c) -target_link_libraries(YitIdGen YitIdHelper) -target_link_libraries(YitIdGen idgen) +target_link_libraries(YitIdGen YitIdHelper pthread) +target_link_libraries(YitIdGen idgen pthread) diff --git a/D/README.md b/D/README.md new file mode 100644 index 0000000..fe57904 --- /dev/null +++ b/D/README.md @@ -0,0 +1,32 @@ + +## 运行环境 + +```sh +$ cd test +$ dub run --compiler=dmd -a=x86_64 +``` + + +## 调用示例(D) + +第1步,**全局** 初始化(应用程序启动时执行一次): +``` +// 创建 IdGeneratorOptions 对象,请在构造函数中输入 WorkerId: +IdGeneratorOptions options = new IdGeneratorOptions(1); +// options.WorkerIdBitLength = 10; // WorkerIdBitLength 默认值6,支持的 WorkerId 最大值为2^6-1,若 WorkerId 超过64,可设置更大的 WorkerIdBitLength +// ...... 其它参数设置参考 IdGeneratorOptions 定义,一般来说,只要再设置 WorkerIdBitLength (决定 WorkerId 的最大值)。 + +// 保存参数(必须的操作,否则以上设置都不能生效): +YitIdHelper.setIdGenerator(options); +// 以上初始化过程只需全局一次,且必须在第2步之前设置。 +``` + +第2步,生成ID: +``` +// 初始化以后,即可在任何需要生成ID的地方,调用以下方法: +long newId = YitIdHelper.nextId(); +``` + +如果基于DI框架集成,可以参考 YitIdHelper 去管理 IdGenerator 对象,须使用 **单例** 模式。 + + diff --git a/D/dub.json b/D/dub.json new file mode 100644 index 0000000..69123f2 --- /dev/null +++ b/D/dub.json @@ -0,0 +1,9 @@ +{ + "authors": [ + "yitter", + "HuntLabs" + ], + "description": "A minimal D application.", + "license": "proprietary", + "name": "yitterd" +} diff --git a/D/source/yitter/contract/IIdGenerator.d b/D/source/yitter/contract/IIdGenerator.d new file mode 100644 index 0000000..3c54ede --- /dev/null +++ b/D/source/yitter/contract/IIdGenerator.d @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.contract.IIdGenerator; + +interface IIdGenerator { + long newLong(); +} diff --git a/D/source/yitter/contract/ISnowWorker.d b/D/source/yitter/contract/ISnowWorker.d new file mode 100644 index 0000000..f6165ff --- /dev/null +++ b/D/source/yitter/contract/ISnowWorker.d @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.contract.ISnowWorker; + +interface ISnowWorker { + long nextId(); +} diff --git a/D/source/yitter/contract/IdGeneratorException.d b/D/source/yitter/contract/IdGeneratorException.d new file mode 100644 index 0000000..da16d87 --- /dev/null +++ b/D/source/yitter/contract/IdGeneratorException.d @@ -0,0 +1,29 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.contract.IdGeneratorException; + +class IdGeneratorException : Exception { + + // this() { + // super(); + // } + + this(string message) { + super(message); + } + + // this(Throwable cause) { + // super(cause); + // } + + this(string message, Throwable cause) { + super(message, cause); + } + + // this(string msgFormat, Object... args) { + // super(string.format(msgFormat, args)); + // } + +} diff --git a/D/source/yitter/contract/IdGeneratorOptions.d b/D/source/yitter/contract/IdGeneratorOptions.d new file mode 100644 index 0000000..088b9e0 --- /dev/null +++ b/D/source/yitter/contract/IdGeneratorOptions.d @@ -0,0 +1,72 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.contract.IdGeneratorOptions; + +import std.datetime; + +/** + * 雪花算法使用的参数 + * 参数说明,参考 README.md 的 “配置参数” 章节。 + */ +class IdGeneratorOptions { + + /** + * 雪花计算方法 + * (1-漂移算法|2-传统算法),默认1 + */ + short Method = 1; + + /** + * 基础时间(ms单位) + * 不能超过当前系统时间 + */ + // long BaseTime = 1582136402000L; + SysTime BaseTime; + + /** + * 机器码 + * 必须由外部设定,最大值 2^WorkerIdBitLength-1 + */ + short WorkerId = 0; + + /** + * 机器码位长 + * 默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) + */ + byte WorkerIdBitLength = 6; + + /** + * 序列数位长 + * 默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) + */ + byte SeqBitLength = 6; + + /** + * 最大序列数(含) + * 设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1]) + */ + short MaxSeqNumber = 0; + + /** + * 最小序列数(含) + * 默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号是0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 + */ + short MinSeqNumber = 5; + + /** + * 最大漂移次数(含) + * 默认2000,推荐范围500-10000(与计算能力有关) + */ + short TopOverCostCount = 2000; + + this() { + BaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2)); + } + + this(short workerId) { + WorkerId = workerId; + BaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2)); + } +} diff --git a/D/source/yitter/contract/OverCostActionArg.d b/D/source/yitter/contract/OverCostActionArg.d new file mode 100644 index 0000000..74d89dc --- /dev/null +++ b/D/source/yitter/contract/OverCostActionArg.d @@ -0,0 +1,52 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.contract.OverCostActionArg; + +/** + * Id生成时回调参数 + */ +class OverCostActionArg { + + /** + * 事件类型 + * 1-开始,2-结束,8-漂移 + */ + int ActionType = 0; + + /** + * 时间戳 + */ + long TimeTick = 0; + + /** + * 机器码 + */ + short WorkerId = 0; + + /** + * + */ + int OverCostCountInOneTerm = 0; + + /** + * 漂移期间生产ID个数 + */ + int GenCountInOneTerm = 0; + + /** + * 漂移周期 + */ + int TermIndex = 0; + + this(short workerId, long timeTick, int actionType, int overCostCountInOneTerm, + int genCountWhenOverCost, int index) { + ActionType = actionType; + TimeTick = timeTick; + WorkerId = workerId; + OverCostCountInOneTerm = overCostCountInOneTerm; + GenCountInOneTerm = genCountWhenOverCost; + TermIndex = index; + } +} diff --git a/D/source/yitter/contract/package.d b/D/source/yitter/contract/package.d new file mode 100644 index 0000000..456a322 --- /dev/null +++ b/D/source/yitter/contract/package.d @@ -0,0 +1,7 @@ +module yitter.contract; + +public import yitter.contract.IdGeneratorException; +public import yitter.contract.IdGeneratorOptions; +public import yitter.contract.IIdGenerator; +public import yitter.contract.ISnowWorker; +public import yitter.contract.OverCostActionArg; \ No newline at end of file diff --git a/D/source/yitter/core/SnowWorkerM1.d b/D/source/yitter/core/SnowWorkerM1.d new file mode 100644 index 0000000..935243b --- /dev/null +++ b/D/source/yitter/core/SnowWorkerM1.d @@ -0,0 +1,237 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.core.SnowWorkerM1; + +import yitter.contract.ISnowWorker; +import yitter.contract.IdGeneratorOptions; +import yitter.contract.OverCostActionArg; +import yitter.contract.IdGeneratorException; + +import std.datetime; + +class SnowWorkerM1 : ISnowWorker { + + /** + * 基础时间 + */ + protected SysTime BaseTime; + + /** + * 机器码 + */ + protected short WorkerId; + + /** + * 机器码位长 + */ + protected byte WorkerIdBitLength; + + /** + * 自增序列数位长 + */ + protected byte SeqBitLength; + + /** + * 最大序列数(含) + */ + protected int MaxSeqNumber; + + /** + * 最小序列数(含) + */ + protected short MinSeqNumber; + + /** + * 最大漂移次数 + */ + protected int TopOverCostCount; + + protected byte _TimestampShift; + // protected __gshared Object _SyncLock; // = new byte[0]; + + protected short _CurrentSeqNumber; + protected long _LastTimeTick = 0; + protected long _TurnBackTimeTick = 0; + protected byte _TurnBackIndex = 0; + + protected bool _IsOverCost = false; + protected int _OverCostCountInOneTerm = 0; + protected int _GenCountInOneTerm = 0; + protected int _TermIndex = 0; + + // shared static this() { + // _SyncLock = new Object(); + // } + + this(IdGeneratorOptions options) { + BaseTime = options.BaseTime != SysTime.min ? options.BaseTime : SysTime(DateTime(2020, 2, 20, 2, 20, 2)); + WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength; + WorkerId = options.WorkerId; + 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; + _TimestampShift = cast(byte) (WorkerIdBitLength + SeqBitLength); + _CurrentSeqNumber = MinSeqNumber; + } + + private void DoGenIdAction(OverCostActionArg arg) { + + } + + private void BeginOverCostAction(long useTimeTick) { + + } + + private void EndOverCostAction(long useTimeTick) { + if (_TermIndex > 10000) { + _TermIndex = 0; + } + } + + private void BeginTurnBackAction(long useTimeTick) { + + } + + private void EndTurnBackAction(long useTimeTick) { + + } + + private long NextOverCostId() { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick > _LastTimeTick) { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_OverCostCountInOneTerm >= TopOverCostCount) { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = GetNextTimeTick(); + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) { + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm++; + _GenCountInOneTerm++; + + return CalcId(_LastTimeTick); + } + + _GenCountInOneTerm++; + return CalcId(_LastTimeTick); + } + + private long NextNormalId() { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick < _LastTimeTick) { + if (_TurnBackTimeTick < 1) { + _TurnBackTimeTick = _LastTimeTick - 1; + _TurnBackIndex++; + + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if (_TurnBackIndex > 4) { + _TurnBackIndex = 1; + } + BeginTurnBackAction(_TurnBackTimeTick); + } + +// try { +// Thread.sleep(1); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + + return CalcTurnBackId(_TurnBackTimeTick); + } + + // 时间追平时,_TurnBackTimeTick清零 + if (_TurnBackTimeTick > 0) { + EndTurnBackAction(_TurnBackTimeTick); + _TurnBackTimeTick = 0; + } + + if (currentTimeTick > _LastTimeTick) { + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) { + BeginOverCostAction(currentTimeTick); + + _TermIndex++; + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm = 1; + _GenCountInOneTerm = 1; + + return CalcId(_LastTimeTick); + } + + return CalcId(_LastTimeTick); + } + + private long CalcId(long useTimeTick) { + long result = ((useTimeTick << _TimestampShift) + + (cast(long) WorkerId << SeqBitLength) + + cast(int) _CurrentSeqNumber); + + _CurrentSeqNumber++; + return result; + } + + private long CalcTurnBackId(long useTimeTick) { + long result = ((useTimeTick << _TimestampShift) + + (cast(long) WorkerId << SeqBitLength) + _TurnBackIndex); + + _TurnBackTimeTick--; + return result; + } + + protected long GetCurrentTimeTick() { + SysTime now = Clock.currTime; + Duration dur = Clock.currTime - BaseTime; + return dur.total!("msecs"); + } + + protected long GetNextTimeTick() { + long tempTimeTicker = GetCurrentTimeTick(); + + while (tempTimeTicker <= _LastTimeTick) { + tempTimeTicker = GetCurrentTimeTick(); + } + + return tempTimeTicker; + } + + override + long nextId() { + synchronized { + return _IsOverCost ? NextOverCostId() : NextNormalId(); + } + } +} + diff --git a/D/source/yitter/core/SnowWorkerM2.d b/D/source/yitter/core/SnowWorkerM2.d new file mode 100644 index 0000000..474f8cc --- /dev/null +++ b/D/source/yitter/core/SnowWorkerM2.d @@ -0,0 +1,50 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.core.SnowWorkerM2; + +import yitter.core.SnowWorkerM1; + +import yitter.contract.IdGeneratorOptions; +import yitter.contract.IdGeneratorException; + +import std.format; + + +/** + * + */ +class SnowWorkerM2 : SnowWorkerM1 { + + this(IdGeneratorOptions options) { + super(options); + } + + override + long nextId() { + synchronized { + long currentTimeTick = GetCurrentTimeTick(); + + if (_LastTimeTick == currentTimeTick) { + if (_CurrentSeqNumber++ > MaxSeqNumber) { + _CurrentSeqNumber = MinSeqNumber; + currentTimeTick = GetNextTimeTick(); + } + } else { + _CurrentSeqNumber = MinSeqNumber; + } + + if (currentTimeTick < _LastTimeTick) { + string msg = format("Time error for %d milliseconds", _LastTimeTick - currentTimeTick); + throw new IdGeneratorException(msg); + } + + _LastTimeTick = currentTimeTick; + long result = ((currentTimeTick << _TimestampShift) + (cast(long) WorkerId << SeqBitLength) + cast(int) _CurrentSeqNumber); + + return result; + } + + } +} diff --git a/D/source/yitter/idgen/DefaultIdGenerator.d b/D/source/yitter/idgen/DefaultIdGenerator.d new file mode 100644 index 0000000..fe33134 --- /dev/null +++ b/D/source/yitter/idgen/DefaultIdGenerator.d @@ -0,0 +1,98 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.idgen.DefaultIdGenerator; + +import yitter.contract.IIdGenerator; +import yitter.contract.ISnowWorker; +import yitter.contract.IdGeneratorException; +import yitter.contract.IdGeneratorOptions; +import yitter.core.SnowWorkerM1; +import yitter.core.SnowWorkerM2; + +import core.thread; +import core.time; + +import std.conv; +import std.datetime; +import std.stdio; + +/** + * + */ +class DefaultIdGenerator : IIdGenerator { + + private __gshared ISnowWorker _SnowWorker = null; + + this(IdGeneratorOptions options) { + if (options is null) { + throw new IdGeneratorException("options error."); + } + + // 1.BaseTime + SysTime MinBaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2)).add!"years"(-50); + if (options.BaseTime < MinBaseTime || options.BaseTime > Clock.currTime) { + throw new IdGeneratorException("BaseTime error."); + } + + // 2.WorkerIdBitLength + if (options.WorkerIdBitLength <= 0) { + throw new IdGeneratorException("WorkerIdBitLength error.(range:[1, 21])"); + } + if (options.WorkerIdBitLength + options.SeqBitLength > 22) { + throw new IdGeneratorException("error:WorkerIdBitLength + SeqBitLength <= 22"); + } + + // 3.WorkerId + int maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; + if (maxWorkerIdNumber == 0) { + maxWorkerIdNumber = 63; + } + if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { + string msg = "WorkerId error. (range:[0, " ~ to!string((maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63)) ~ "]"; + throw new IdGeneratorException(msg); + } + + // 4.SeqBitLength + if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { + throw new IdGeneratorException("SeqBitLength error. (range:[2, 21])"); + } + + // 5.MaxSeqNumber + int maxSeqNumber = (1 << options.SeqBitLength) - 1; + if (maxSeqNumber == 0) { + maxSeqNumber = 63; + } + if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) { + throw new IdGeneratorException("MaxSeqNumber error. (range:[1, " ~ maxSeqNumber.to!string() ~ "]"); + } + + // 6.MinSeqNumber + if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) { + throw new IdGeneratorException("MinSeqNumber error. (range:[5, " ~ maxSeqNumber.to!string() ~ "]"); + } + + switch (options.Method) { + case 2: + _SnowWorker = new SnowWorkerM2(options); + break; + case 1: + default: + _SnowWorker = new SnowWorkerM1(options); + break; + } + + if (options.Method == 1) { + try { + Thread.sleep(500.msecs); + } catch (Exception e) { + writeln(e.toString()); + } + } + } + + long newLong() { + return _SnowWorker.nextId(); + } +} diff --git a/D/source/yitter/idgen/YitIdHelper.d b/D/source/yitter/idgen/YitIdHelper.d new file mode 100644 index 0000000..d389d7b --- /dev/null +++ b/D/source/yitter/idgen/YitIdHelper.d @@ -0,0 +1,43 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +module yitter.idgen.YitIdHelper; + +import yitter.idgen.DefaultIdGenerator; + +import yitter.contract.IIdGenerator; +import yitter.contract.IdGeneratorException; +import yitter.contract.IdGeneratorOptions; + +import std.concurrency : initOnce; + +/** + * 这是一个调用的例子,默认情况下,单机集成者可以直接使用 nextId()。 + */ +class YitIdHelper { + + private __gshared IIdGenerator idGenInstance = null; + + static IIdGenerator getIdGenInstance() { + return initOnce!idGenInstance(new DefaultIdGenerator(new IdGeneratorOptions(1))); + + } + + /** + * 设置参数,建议程序初始化时执行一次 + */ + static void setIdGenerator(IdGeneratorOptions options) { + idGenInstance = new DefaultIdGenerator(options); + } + + /** + * 生成新的Id + * 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 + * + * @return + */ + static long nextId() { + return getIdGenInstance().newLong(); + } +} diff --git a/D/source/yitter/package.d b/D/source/yitter/package.d new file mode 100644 index 0000000..2f044e6 --- /dev/null +++ b/D/source/yitter/package.d @@ -0,0 +1,6 @@ +module yitter; + +public import yitter.contract; + +public import yitter.idgen.DefaultIdGenerator; +public import yitter.idgen.YitIdHelper; diff --git a/D/test/dub.json b/D/test/dub.json new file mode 100644 index 0000000..67bf2cd --- /dev/null +++ b/D/test/dub.json @@ -0,0 +1,14 @@ +{ + "authors": [ + "yitter", + "HuntLabs" + ], + "description": "A minimal D application.", + "license": "proprietary", + "name": "test", + "dependencies": { + "yitterd" : { + "path": "../" + } + } +} \ No newline at end of file diff --git a/D/test/source/GenTest.d b/D/test/source/GenTest.d new file mode 100644 index 0000000..f60d39f --- /dev/null +++ b/D/test/source/GenTest.d @@ -0,0 +1,38 @@ +module GenTest; + +import yitter.contract.IIdGenerator; + +import std.conv; +import std.datetime; +import std.stdio; + + +class GenTest { + + private IIdGenerator IdGen; + private int GenIdCount; + private int WorkerId; + + this(IIdGenerator idGen, int genIdCount, int workerId) { + GenIdCount = genIdCount; + IdGen = idGen; + WorkerId = workerId; + } + + void GenStart() { + MonoTime start = MonoTime.currTime(); + long id = 0; + + for (int i = 0; i < GenIdCount; i++) { + id = IdGen.newLong(); + } + + MonoTime end = MonoTime.currTime(); + Duration dur = end - start; + + // writeln(id); + writeln("++++++++++++++++++++++++++++++++++++++++WorkerId: " + ~ WorkerId.to!string() ~ ", total: " ~ dur.total!("msecs").to!string() ~ " ms"); + + } +} diff --git a/D/test/source/app.d b/D/test/source/app.d new file mode 100644 index 0000000..c2c9349 --- /dev/null +++ b/D/test/source/app.d @@ -0,0 +1,52 @@ +import std.stdio; + +import yitter; +import GenTest; + +import core.thread; + +import std.conv; +import std.datetime; +import std.stdio; + +/** + * 测试结果: + * (1):1W并发,方法 1只要 1ms.而方法 2 要 180ms。 + * (2):5W并发,方法 1只要 3ms.而方法 2 要 900ms。 + * [不同CPU可能结果有差异,但相对大小不变] + * 默认配置下,最佳性能是5W/s-8W/s + */ +enum int genIdCount = 50000; + +//1-漂移算法,2-传统算法 +enum short method = 1; + +void main() +{ + + IdGeneratorOptions options = new IdGeneratorOptions(); + + options.Method = method; + options.BaseTime = SysTime(DateTime(2020, 2, 20, 21, 51, 33)); + options.WorkerId = 1; + + IIdGenerator idGen = new DefaultIdGenerator(options); + GenTest.GenTest genTest = new GenTest.GenTest(idGen, genIdCount, options.WorkerId); + + // 首先测试一下 IdHelper 方法,获取单个Id + YitIdHelper.setIdGenerator(options); + long newId = YitIdHelper.nextId(); + writeln("====================================="); + writeln("这是用方法 " ~ method.to!string() ~ " 生成的 Id:" ~ newId.to!string()); + + // 然后循环测试一下,看看并发请求时的耗时情况 + try { + while (true) { + genTest.GenStart(); + // Thread.sleep(200.msecs); // 每隔1秒执行一次GenStart + // writeln("Hello World! D"); + } + } catch (Exception e) { + writeln(e.toString()); + } +}