|
|
@@ -1,26 +1,28 @@
|
|
|
using System;
|
|
|
using System.Runtime.InteropServices;
|
|
|
-using MongoDB.Bson;
|
|
|
+using MemoryPack;
|
|
|
|
|
|
namespace ET
|
|
|
{
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
public struct IdStruct
|
|
|
{
|
|
|
- public int Process; // 18bit
|
|
|
+ public short Process; // 14bit
|
|
|
public uint Time; // 30bit
|
|
|
- public ushort Value; // 16bit
|
|
|
+ public uint Value; // 20bit
|
|
|
|
|
|
public long ToLong()
|
|
|
{
|
|
|
ulong result = 0;
|
|
|
+ result |= (ushort) this.Process;
|
|
|
+ result <<= 14;
|
|
|
+ result |= this.Time;
|
|
|
+ result <<= 30;
|
|
|
result |= this.Value;
|
|
|
- result |= (ulong) this.Process << 16;
|
|
|
- result |= (ulong) this.Time << 34;
|
|
|
return (long) result;
|
|
|
}
|
|
|
|
|
|
- public IdStruct(uint time, int process, ushort value)
|
|
|
+ public IdStruct(uint time, short process, uint value)
|
|
|
{
|
|
|
this.Process = process;
|
|
|
this.Time = time;
|
|
|
@@ -30,11 +32,11 @@ namespace ET
|
|
|
public IdStruct(long id)
|
|
|
{
|
|
|
ulong result = (ulong) id;
|
|
|
- this.Value = (ushort) (result & ushort.MaxValue);
|
|
|
- result >>= 16;
|
|
|
- this.Process = (int) (result & IdGenerater.Mask18bit);
|
|
|
- result >>= 18;
|
|
|
- this.Time = (uint) result;
|
|
|
+ this.Value = (ushort) (result & IdGenerater.Mask20bit);
|
|
|
+ result >>= 20;
|
|
|
+ this.Time = (uint) result & IdGenerater.Mask30bit;
|
|
|
+ result >>= 30;
|
|
|
+ this.Process = (short) (result & IdGenerater.Mask14bit);
|
|
|
}
|
|
|
|
|
|
public override string ToString()
|
|
|
@@ -42,239 +44,107 @@ namespace ET
|
|
|
return $"process: {this.Process}, time: {this.Time}, value: {this.Value}";
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
public struct InstanceIdStruct
|
|
|
{
|
|
|
- public int Process; // 18bit
|
|
|
- public uint Time; // 当年开始的tick 28bit
|
|
|
- public uint Value; // 18bit
|
|
|
+ public uint Time; // 32bit
|
|
|
+ public uint Value; // 32bit
|
|
|
|
|
|
public long ToLong()
|
|
|
{
|
|
|
ulong result = 0;
|
|
|
+ result |= this.Time;
|
|
|
+ result <<= 32;
|
|
|
result |= this.Value;
|
|
|
- result |= (ulong)this.Process << 18;
|
|
|
- result |= (ulong) this.Time << 36;
|
|
|
return (long) result;
|
|
|
}
|
|
|
|
|
|
- public InstanceIdStruct(long id)
|
|
|
- {
|
|
|
- ulong result = (ulong) id;
|
|
|
- this.Value = (uint)(result & IdGenerater.Mask18bit);
|
|
|
- result >>= 18;
|
|
|
- this.Process = (int)(result & IdGenerater.Mask18bit);
|
|
|
- result >>= 18;
|
|
|
- this.Time = (uint)result;
|
|
|
- }
|
|
|
-
|
|
|
- public InstanceIdStruct(uint time, int process, uint value)
|
|
|
- {
|
|
|
- this.Time = time;
|
|
|
- this.Process = process;
|
|
|
- this.Value = value;
|
|
|
- }
|
|
|
-
|
|
|
- // 给SceneId使用
|
|
|
- public InstanceIdStruct(int process, uint value)
|
|
|
+ public InstanceIdStruct(uint time, uint value)
|
|
|
{
|
|
|
- this.Time = 0;
|
|
|
- this.Process = process;
|
|
|
+ this.Time = (uint)time;
|
|
|
this.Value = value;
|
|
|
}
|
|
|
|
|
|
- public override string ToString()
|
|
|
- {
|
|
|
- return $"process: {this.Process}, value: {this.Value} time: {this.Time}";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
- public struct UnitIdStruct
|
|
|
- {
|
|
|
- public uint Time; // 30bit 34年
|
|
|
- public ushort Zone; // 10bit 1024个区
|
|
|
- public byte ProcessMode; // 8bit Process % 256 一个区最多256个进程
|
|
|
- public ushort Value; // 16bit 每秒每个进程最大16K个Unit
|
|
|
-
|
|
|
- public long ToLong()
|
|
|
+ public InstanceIdStruct(long id)
|
|
|
{
|
|
|
- ulong result = 0;
|
|
|
- result |= this.Value;
|
|
|
- result |= (uint)this.ProcessMode << 16;
|
|
|
- result |= (ulong) this.Zone << 24;
|
|
|
- result |= (ulong) this.Time << 34;
|
|
|
- return (long) result;
|
|
|
+ ulong result = (ulong) id;
|
|
|
+ this.Value = (uint)(result & uint.MaxValue);
|
|
|
+ result >>= 32;
|
|
|
+ this.Time = (uint)(result & uint.MaxValue);
|
|
|
}
|
|
|
|
|
|
- public UnitIdStruct(int zone, int process, uint time, ushort value)
|
|
|
- {
|
|
|
- this.Time = time;
|
|
|
- this.ProcessMode = (byte)(process % 256);
|
|
|
- this.Value = value;
|
|
|
- this.Zone = (ushort)zone;
|
|
|
- }
|
|
|
-
|
|
|
- public UnitIdStruct(long id)
|
|
|
- {
|
|
|
- ulong result = (ulong) id;
|
|
|
- this.Value = (ushort)(result & ushort.MaxValue);
|
|
|
- result >>= 16;
|
|
|
- this.ProcessMode = (byte)(result & byte.MaxValue);
|
|
|
- result >>= 8;
|
|
|
- this.Zone = (ushort)(result & 0x03ff);
|
|
|
- result >>= 10;
|
|
|
- this.Time = (uint)result;
|
|
|
- }
|
|
|
-
|
|
|
public override string ToString()
|
|
|
{
|
|
|
- return $"ProcessMode: {this.ProcessMode}, value: {this.Value} time: {this.Time}";
|
|
|
- }
|
|
|
-
|
|
|
- public static int GetUnitZone(long unitId)
|
|
|
- {
|
|
|
- int v = (int) ((unitId >> 24) & 0x03ff); // 取出10bit
|
|
|
- return v;
|
|
|
+ return $"time: {this.Time}, value: {this.Value}";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class IdGenerater: VProcessSingleton<IdGenerater>
|
|
|
{
|
|
|
- public const int Mask18bit = 0x03ffff;
|
|
|
-
|
|
|
public const int MaxZone = 1024;
|
|
|
|
|
|
- private long epoch2020;
|
|
|
- private ushort value;
|
|
|
+ public const int Mask14bit = 0x3fff;
|
|
|
+ public const int Mask30bit = 0x3fffffff;
|
|
|
+ public const int Mask20bit = 0xfffff;
|
|
|
+
|
|
|
+ private long epoch2022;
|
|
|
+ private uint value;
|
|
|
private uint lastIdTime;
|
|
|
-
|
|
|
|
|
|
- private long epochThisYear;
|
|
|
private uint instanceIdValue;
|
|
|
- private uint lastInstanceIdTime;
|
|
|
-
|
|
|
|
|
|
- private ushort unitIdValue;
|
|
|
- private uint lastUnitIdTime;
|
|
|
-
|
|
|
public IdGenerater()
|
|
|
{
|
|
|
long epoch1970tick = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
|
|
|
- this.epoch2020 = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
|
|
|
- this.epochThisYear = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
|
|
|
-
|
|
|
- this.lastInstanceIdTime = TimeSinceThisYear();
|
|
|
- if (this.lastInstanceIdTime <= 0)
|
|
|
- {
|
|
|
- Log.Warning($"lastInstanceIdTime less than 0: {this.lastInstanceIdTime}");
|
|
|
- this.lastInstanceIdTime = 1;
|
|
|
- }
|
|
|
- this.lastIdTime = TimeSince2020();
|
|
|
+ this.epoch2022 = new DateTime(2022, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
|
|
|
+ this.lastIdTime = TimeSince2022();
|
|
|
if (this.lastIdTime <= 0)
|
|
|
{
|
|
|
Log.Warning($"lastIdTime less than 0: {this.lastIdTime}");
|
|
|
this.lastIdTime = 1;
|
|
|
}
|
|
|
- this.lastUnitIdTime = TimeSince2020();
|
|
|
- if (this.lastUnitIdTime <= 0)
|
|
|
- {
|
|
|
- Log.Warning($"lastUnitIdTime less than 0: {this.lastUnitIdTime}");
|
|
|
- this.lastUnitIdTime = 1;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
- private uint TimeSince2020()
|
|
|
+ private uint TimeSince2022()
|
|
|
{
|
|
|
- uint a = (uint)((TimeInfo.Instance.FrameTime - this.epoch2020) / 1000);
|
|
|
+ uint a = (uint)((TimeInfo.Instance.FrameTime - this.epoch2022) / 1000);
|
|
|
return a;
|
|
|
}
|
|
|
|
|
|
- private uint TimeSinceThisYear()
|
|
|
- {
|
|
|
- uint a = (uint)((TimeInfo.Instance.FrameTime - this.epochThisYear) / 1000);
|
|
|
- return a;
|
|
|
- }
|
|
|
-
|
|
|
- public long GenerateInstanceId()
|
|
|
- {
|
|
|
- uint time = TimeSinceThisYear();
|
|
|
-
|
|
|
- if (time > this.lastInstanceIdTime)
|
|
|
- {
|
|
|
- this.lastInstanceIdTime = time;
|
|
|
- this.instanceIdValue = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ++this.instanceIdValue;
|
|
|
-
|
|
|
- if (this.instanceIdValue > IdGenerater.Mask18bit - 1) // 18bit
|
|
|
- {
|
|
|
- ++this.lastInstanceIdTime; // 借用下一秒
|
|
|
- this.instanceIdValue = 0;
|
|
|
-
|
|
|
- Log.Error($"instanceid count per sec overflow: {time} {this.lastInstanceIdTime}");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- InstanceIdStruct instanceIdStruct = new InstanceIdStruct(this.lastInstanceIdTime, Options.Instance.Process, this.instanceIdValue);
|
|
|
- return instanceIdStruct.ToLong();
|
|
|
- }
|
|
|
-
|
|
|
public long GenerateId()
|
|
|
{
|
|
|
- uint time = TimeSince2020();
|
|
|
+ uint time = TimeSince2022();
|
|
|
|
|
|
+ // 时间不会倒退
|
|
|
if (time > this.lastIdTime)
|
|
|
{
|
|
|
this.lastIdTime = time;
|
|
|
- this.value = 0;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- ++this.value;
|
|
|
-
|
|
|
- if (value > ushort.MaxValue - 1)
|
|
|
- {
|
|
|
- this.value = 0;
|
|
|
- ++this.lastIdTime; // 借用下一秒
|
|
|
- Log.Error($"id count per sec overflow: {time} {this.lastIdTime}");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- IdStruct idStruct = new IdStruct(this.lastIdTime, Options.Instance.Process, value);
|
|
|
+ this.value = IdValueGenerater.Instance.Value;
|
|
|
+
|
|
|
+ IdStruct idStruct = new(this.lastIdTime, (short)Options.Instance.Process, value);
|
|
|
return idStruct.ToLong();
|
|
|
}
|
|
|
|
|
|
- public long GenerateUnitId(int zone)
|
|
|
+ public long GenerateInstanceId()
|
|
|
{
|
|
|
- if (zone > MaxZone)
|
|
|
- {
|
|
|
- throw new Exception($"zone > MaxZone: {zone}");
|
|
|
- }
|
|
|
- uint time = TimeSince2020();
|
|
|
+ uint time = this.TimeSince2022();
|
|
|
|
|
|
- if (time > this.lastUnitIdTime)
|
|
|
+ // 时间不会倒退
|
|
|
+ if (time > this.lastIdTime)
|
|
|
{
|
|
|
- this.lastUnitIdTime = time;
|
|
|
- this.unitIdValue = 0;
|
|
|
+ this.lastIdTime = time;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- ++this.unitIdValue;
|
|
|
+ ++this.instanceIdValue;
|
|
|
|
|
|
- if (this.unitIdValue > ushort.MaxValue - 1)
|
|
|
- {
|
|
|
- this.unitIdValue = 0;
|
|
|
- ++this.lastUnitIdTime; // 借用下一秒
|
|
|
- Log.Error($"unitid count per sec overflow: {time} {this.lastUnitIdTime}");
|
|
|
- }
|
|
|
+ if (this.instanceIdValue > Mask20bit - 1)
|
|
|
+ {
|
|
|
+ this.instanceIdValue = 0;
|
|
|
}
|
|
|
|
|
|
- UnitIdStruct unitIdStruct = new UnitIdStruct(zone, Options.Instance.Process, this.lastUnitIdTime, this.unitIdValue);
|
|
|
- return unitIdStruct.ToLong();
|
|
|
+ InstanceIdStruct instanceIdStruct = new(this.lastIdTime, this.instanceIdValue);
|
|
|
+ return instanceIdStruct.ToLong();
|
|
|
}
|
|
|
}
|
|
|
}
|