@@ -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 |
@@ -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) | |||
@@ -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 对象,须使用 **单例** 模式。 | |||
@@ -0,0 +1,9 @@ | |||
{ | |||
"authors": [ | |||
"yitter", | |||
"HuntLabs" | |||
], | |||
"description": "A minimal D application.", | |||
"license": "proprietary", | |||
"name": "yitterd" | |||
} |
@@ -0,0 +1,9 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
module yitter.contract.IIdGenerator; | |||
interface IIdGenerator { | |||
long newLong(); | |||
} |
@@ -0,0 +1,9 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
module yitter.contract.ISnowWorker; | |||
interface ISnowWorker { | |||
long nextId(); | |||
} |
@@ -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)); | |||
// } | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; |
@@ -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(); | |||
} | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
module yitter; | |||
public import yitter.contract; | |||
public import yitter.idgen.DefaultIdGenerator; | |||
public import yitter.idgen.YitIdHelper; |
@@ -0,0 +1,14 @@ | |||
{ | |||
"authors": [ | |||
"yitter", | |||
"HuntLabs" | |||
], | |||
"description": "A minimal D application.", | |||
"license": "proprietary", | |||
"name": "test", | |||
"dependencies": { | |||
"yitterd" : { | |||
"path": "../" | |||
} | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |