Browse Source

!7 D语言版本性能提升

* Better performace for D.
tags/v1.1.0
BitWorld yitter 3 years ago
parent
commit
7673c9f441
10 changed files with 196 additions and 32 deletions
  1. +1
    -1
      C/source/.gitignore
  2. +6
    -6
      D/.gitignore
  3. +1
    -4
      D/source/yitter/contract/IdGeneratorOptions.d
  4. +173
    -0
      D/source/yitter/core/DateTimeHelper.d
  5. +6
    -13
      D/source/yitter/core/SnowWorkerM1.d
  6. +1
    -2
      D/source/yitter/core/SnowWorkerM2.d
  7. +3
    -2
      D/source/yitter/idgen/DefaultIdGenerator.d
  8. +1
    -0
      D/source/yitter/package.d
  9. +1
    -1
      D/test/source/GenTest.d
  10. +3
    -3
      D/test/source/app.d

+ 1
- 1
C/source/.gitignore View File

@@ -1,7 +1,7 @@
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.


./build/*
build/*


# User-specific files # User-specific files
*.suo *.suo


+ 6
- 6
D/.gitignore View File

@@ -1,9 +1,9 @@


.DS_Store .DS_Store
./test/test
./libyitterd.a
./dub.*.json
./.dub/*
./test/.dub/*
./test/dub.*.json
test/test
libyitterd.a
dub.*.json
.dub/*
test/.dub/*
test/dub.*.json



+ 1
- 4
D/source/yitter/contract/IdGeneratorOptions.d View File

@@ -22,8 +22,7 @@ class IdGeneratorOptions {
* 基础时间(ms单位) * 基础时间(ms单位)
* 不能超过当前系统时间 * 不能超过当前系统时间
*/ */
// long BaseTime = 1582136402000L;
SysTime BaseTime;
long BaseTime = 1582136402000L;
/** /**
* 机器码 * 机器码
@@ -62,11 +61,9 @@ class IdGeneratorOptions {
short TopOverCostCount = 2000; short TopOverCostCount = 2000;
this() { this() {
BaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2));
} }
this(short workerId) { this(short workerId) {
WorkerId = workerId; WorkerId = workerId;
BaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2));
} }
} }

+ 173
- 0
D/source/yitter/core/DateTimeHelper.d View File

@@ -0,0 +1,173 @@
module yitter.core.DateTimeHelper;

import core.stdc.time;
import std.datetime : convert;
import std.string;

enum TimeUnit : string {
Year = "years",
Month = "months",
Week = "weeks",
Day = "days",
Hour = "hours",
Second = "seconds",
Millisecond = "msecs",
Microsecond = "usecs",
HectoNanosecond = "hnsecs",
Nanosecond = "nsecs"
}


/**
*
*/
class DateTimeHelper {
/**
* Returns the current time in milliseconds. Note that
* while the unit of time of the return value is a millisecond,
* the granularity of the value depends on the underlying
* operating system and may be larger. For example, many
* operating systems measure time in units of tens of
* milliseconds.
*
* <p> See the description of the class {@code Date} for
* a discussion of slight discrepancies that may arise between
* "computer time" and coordinated universal time (UTC).
*
* @return the difference, measured in milliseconds, between
* the current time and midnight, January 1, 1970 UTC.
*/
static long currentTimeMillis() @trusted @property {
return currentTime!(TimeUnit.Millisecond)();
}

static long currentTimeNsecs() @trusted @property {
return currentTime!(TimeUnit.Nanosecond)();
}

static long currentUnixTime() @trusted @property {
return currentTime!(TimeUnit.Second)();
}

alias currentTimeSecond = currentUnixTime;

/**
*
*/
static long currentTime(TimeUnit targetUnit)() @trusted @property {
version (Windows) {
import core.sys.windows.winbase;
import core.sys.windows.winnt;

/**
http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/
https://stackoverflow.com/questions/10849717/what-is-the-significance-of-january-1-1601
https://stackoverflow.com/questions/1090869/why-is-1-1-1970-the-epoch-time
https://www.unixtimestamp.com/
*/
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
ULARGE_INTEGER date, adjust;
date.HighPart = fileTime.dwHighDateTime;
date.LowPart = fileTime.dwLowDateTime;

// 100-nanoseconds = milliseconds * 10000
adjust.QuadPart = 11644473600000 * 10000;

// removes the diff between 1970 and 1601
date.QuadPart -= adjust.QuadPart;

// converts back from 100-nanoseconds to milliseconds
return convert!(TimeUnit.HectoNanosecond, targetUnit)(date.QuadPart);

} else version (Posix) {
import core.sys.posix.signal : timespec;
version (OSX) {
import core.sys.posix.sys.time : gettimeofday, timeval;

timeval tv = void;
// Posix gettimeofday called with a valid timeval address
// and a null second parameter doesn't fail.
gettimeofday(&tv, null);
return convert!(TimeUnit.Second, targetUnit)(tv.tv_sec) +
convert!(TimeUnit.Microsecond, targetUnit)(tv.tv_usec);

} else version (linux) {
import core.sys.linux.time : CLOCK_REALTIME_COARSE;
import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;

timespec ts = void;
immutable error = clock_gettime(CLOCK_REALTIME, &ts);
// Posix clock_gettime called with a valid address and valid clock_id is only
// permitted to fail if the number of seconds does not fit in time_t. If tv_sec
// is long or larger overflow won't happen before 292 billion years A.D.
static if (ts.tv_sec.max < long.max) {
if (error)
throw new TimeException("Call to clock_gettime() failed");
}
return convert!(TimeUnit.Second, targetUnit)(ts.tv_sec) +
convert!(TimeUnit.Nanosecond, targetUnit)(ts.tv_nsec);

} else version (FreeBSD) {
import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME;

timespec ts = void;
immutable error = clock_gettime(CLOCK_REALTIME, &ts);
// Posix clock_gettime called with a valid address and valid clock_id is only
// permitted to fail if the number of seconds does not fit in time_t. If tv_sec
// is long or larger overflow won't happen before 292 billion years A.D.
static if (ts.tv_sec.max < long.max) {
if (error)
throw new TimeException("Call to clock_gettime() failed");
}
return convert!(TimeUnit.Second, targetUnit)(ts.tv_sec) +
convert!(TimeUnit.Nanosecond, targetUnit)(ts.tv_nsec);
} else version (NetBSD) {
import core.sys.netbsd.time : clock_gettime, CLOCK_REALTIME;

timespec ts = void;
immutable error = clock_gettime(CLOCK_REALTIME, &ts);
// Posix clock_gettime called with a valid address and valid clock_id is only
// permitted to fail if the number of seconds does not fit in time_t. If tv_sec
// is long or larger overflow won't happen before 292 billion years A.D.
static if (ts.tv_sec.max < long.max) {
if (error)
throw new TimeException("Call to clock_gettime() failed");
}
return convert!(TimeUnit.Second, targetUnit)(ts.tv_sec) +
convert!(TimeUnit.Nanosecond, targetUnit)(ts.tv_nsec);
} else version (DragonFlyBSD) {
import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME;

timespec ts = void;
immutable error = clock_gettime(CLOCK_REALTIME, &ts);
// Posix clock_gettime called with a valid address and valid clock_id is only
// permitted to fail if the number of seconds does not fit in time_t. If tv_sec
// is long or larger overflow won't happen before 292 billion years A.D.
static if (ts.tv_sec.max < long.max) {
if (error)
throw new TimeException("Call to clock_gettime() failed");
}
return convert!(TimeUnit.Second, targetUnit)(ts.tv_sec) +
convert!(TimeUnit.Nanosecond, targetUnit)(ts.tv_nsec);
} else version (Solaris) {
import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME;

timespec ts = void;
immutable error = clock_gettime(CLOCK_REALTIME, &ts);
// Posix clock_gettime called with a valid address and valid clock_id is only
// permitted to fail if the number of seconds does not fit in time_t. If tv_sec
// is long or larger overflow won't happen before 292 billion years A.D.
static if (ts.tv_sec.max < long.max) {
if (error)
throw new TimeException("Call to clock_gettime() failed");
}
return convert!(TimeUnit.Second, targetUnit)(ts.tv_sec) +
convert!(TimeUnit.Nanosecond, targetUnit)(ts.tv_nsec);
} else
static assert(0, "Unsupported OS");
} else
static assert(0, "Unsupported OS");
}

}

+ 6
- 13
D/source/yitter/core/SnowWorkerM1.d View File

@@ -4,6 +4,7 @@
*/ */
module yitter.core.SnowWorkerM1; module yitter.core.SnowWorkerM1;
import yitter.core.DateTimeHelper;
import yitter.contract.ISnowWorker; import yitter.contract.ISnowWorker;
import yitter.contract.IdGeneratorOptions; import yitter.contract.IdGeneratorOptions;
import yitter.contract.OverCostActionArg; import yitter.contract.OverCostActionArg;
@@ -11,12 +12,13 @@ import yitter.contract.IdGeneratorException;
import std.datetime; import std.datetime;
class SnowWorkerM1 : ISnowWorker { class SnowWorkerM1 : ISnowWorker {
/** /**
* 基础时间 * 基础时间
*/ */
protected SysTime BaseTime;
protected long BaseTime;
/** /**
* 机器码 * 机器码
@@ -49,7 +51,6 @@ class SnowWorkerM1 : ISnowWorker {
protected int TopOverCostCount; protected int TopOverCostCount;
protected byte _TimestampShift; protected byte _TimestampShift;
// protected __gshared Object _SyncLock; // = new byte[0];
protected short _CurrentSeqNumber; protected short _CurrentSeqNumber;
protected long _LastTimeTick = 0; protected long _LastTimeTick = 0;
@@ -61,12 +62,8 @@ class SnowWorkerM1 : ISnowWorker {
protected int _GenCountInOneTerm = 0; protected int _GenCountInOneTerm = 0;
protected int _TermIndex = 0; protected int _TermIndex = 0;
// shared static this() {
// _SyncLock = new Object();
// }
this(IdGeneratorOptions options) { this(IdGeneratorOptions options) {
BaseTime = options.BaseTime != SysTime.min ? options.BaseTime : SysTime(DateTime(2020, 2, 20, 2, 20, 2));
BaseTime = options.BaseTime != 0 ? options.BaseTime : 1582136402000L;
WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength; WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength;
WorkerId = options.WorkerId; WorkerId = options.WorkerId;
SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength;
@@ -212,14 +209,11 @@ class SnowWorkerM1 : ISnowWorker {
} }
protected long GetCurrentTimeTick() { protected long GetCurrentTimeTick() {
SysTime now = Clock.currTime;
Duration dur = Clock.currTime - BaseTime;
return dur.total!("msecs");
return DateTimeHelper.currentTimeMillis - BaseTime;
} }
protected long GetNextTimeTick() { protected long GetNextTimeTick() {
long tempTimeTicker = GetCurrentTimeTick(); long tempTimeTicker = GetCurrentTimeTick();
while (tempTimeTicker <= _LastTimeTick) { while (tempTimeTicker <= _LastTimeTick) {
tempTimeTicker = GetCurrentTimeTick(); tempTimeTicker = GetCurrentTimeTick();
} }
@@ -227,8 +221,7 @@ class SnowWorkerM1 : ISnowWorker {
return tempTimeTicker; return tempTimeTicker;
} }
override
long nextId() {
override long nextId() {
synchronized { synchronized {
return _IsOverCost ? NextOverCostId() : NextNormalId(); return _IsOverCost ? NextOverCostId() : NextNormalId();
} }


+ 1
- 2
D/source/yitter/core/SnowWorkerM2.d View File

@@ -21,8 +21,7 @@ class SnowWorkerM2 : SnowWorkerM1 {
super(options); super(options);
} }
override
long nextId() {
override long nextId() {
synchronized { synchronized {
long currentTimeTick = GetCurrentTimeTick(); long currentTimeTick = GetCurrentTimeTick();


+ 3
- 2
D/source/yitter/idgen/DefaultIdGenerator.d View File

@@ -8,6 +8,8 @@ import yitter.contract.IIdGenerator;
import yitter.contract.ISnowWorker; import yitter.contract.ISnowWorker;
import yitter.contract.IdGeneratorException; import yitter.contract.IdGeneratorException;
import yitter.contract.IdGeneratorOptions; import yitter.contract.IdGeneratorOptions;
import yitter.core.DateTimeHelper;
import yitter.core.SnowWorkerM1; import yitter.core.SnowWorkerM1;
import yitter.core.SnowWorkerM2; import yitter.core.SnowWorkerM2;
@@ -31,8 +33,7 @@ class DefaultIdGenerator : IIdGenerator {
} }
// 1.BaseTime // 1.BaseTime
SysTime MinBaseTime = SysTime(DateTime(2020, 2, 20, 2, 20, 2)).add!"years"(-50);
if (options.BaseTime < MinBaseTime || options.BaseTime > Clock.currTime) {
if (options.BaseTime < 315504000000L || options.BaseTime > DateTimeHelper.currentTimeMillis) {
throw new IdGeneratorException("BaseTime error."); throw new IdGeneratorException("BaseTime error.");
} }


+ 1
- 0
D/source/yitter/package.d View File

@@ -1,6 +1,7 @@
module yitter; module yitter;


public import yitter.contract; public import yitter.contract;
public import yitter.core.DateTimeHelper;


public import yitter.idgen.DefaultIdGenerator; public import yitter.idgen.DefaultIdGenerator;
public import yitter.idgen.YitIdHelper; public import yitter.idgen.YitIdHelper;

+ 1
- 1
D/test/source/GenTest.d View File

@@ -32,7 +32,7 @@ class GenTest {
// writeln(id); // writeln(id);
writeln("++++++++++++++++++++++++++++++++++++++++WorkerId: " writeln("++++++++++++++++++++++++++++++++++++++++WorkerId: "
~ WorkerId.to!string() ~ ", total: " ~ dur.total!("msecs").to!string() ~ " ms");
~ WorkerId.to!string() ~ ", total: " ~ dur.total!("usecs").to!string() ~ " us");
} }
} }

+ 3
- 3
D/test/source/app.d View File

@@ -27,7 +27,7 @@ void main()
IdGeneratorOptions options = new IdGeneratorOptions(); IdGeneratorOptions options = new IdGeneratorOptions();


options.Method = method; options.Method = method;
options.BaseTime = SysTime(DateTime(2020, 2, 20, 21, 51, 33));
options.BaseTime = 1582206693000L;
options.WorkerId = 1; options.WorkerId = 1;


IIdGenerator idGen = new DefaultIdGenerator(options); IIdGenerator idGen = new DefaultIdGenerator(options);
@@ -37,13 +37,13 @@ void main()
YitIdHelper.setIdGenerator(options); YitIdHelper.setIdGenerator(options);
long newId = YitIdHelper.nextId(); long newId = YitIdHelper.nextId();
writeln("====================================="); writeln("=====================================");
writeln("这是用方法 " ~ method.to!string() ~ " 生成的 Id:" ~ newId.to!string());
writeln("Method " ~ method.to!string() ~ " used, the result Id:" ~ newId.to!string());


// 然后循环测试一下,看看并发请求时的耗时情况 // 然后循环测试一下,看看并发请求时的耗时情况
try { try {
while (true) { while (true) {
genTest.GenStart(); genTest.GenStart();
// Thread.sleep(200.msecs); // 每隔1秒执行一次GenStart
Thread.sleep(1000.msecs);
// writeln("Hello World! D"); // writeln("Hello World! D");
} }
} catch (Exception e) { } catch (Exception e) {


Loading…
Cancel
Save