@@ -42,7 +42,7 @@ namespace Yitter.OrgSystem.TestA | |||||
} | } | ||||
DateTime end = DateTime.Now; | DateTime end = DateTime.Now; | ||||
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++WorkerId: {WorkerId}, total: {(end - start).TotalSeconds} s"); | |||||
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++WorkerId: {WorkerId}, total: {(end - start).TotalMilliseconds} ms"); | |||||
Interlocked.Increment(ref Program.Count); | Interlocked.Increment(ref Program.Count); | ||||
} | } | ||||
} | } | ||||
@@ -1,6 +1,7 @@ | |||||
using System; | using System; | ||||
using System.Collections; | using System.Collections; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Runtime.InteropServices; | |||||
using System.Threading; | using System.Threading; | ||||
using Yitter.IdGenerator; | using Yitter.IdGenerator; | ||||
@@ -25,23 +26,24 @@ namespace Yitter.OrgSystem.TestA | |||||
static void Main(string[] args) | static void Main(string[] args) | ||||
{ | { | ||||
Console.WriteLine("Hello World! C#"); | |||||
var options = new IdGeneratorOptions() | var options = new IdGeneratorOptions() | ||||
{ | { | ||||
Method = method, | Method = method, | ||||
WorkerId = 1, | WorkerId = 1, | ||||
//TopOverCostCount = 2000, | |||||
//WorkerIdBitLength = 1, | |||||
//SeqBitLength = 2, | |||||
WorkerIdBitLength = 6, | |||||
SeqBitLength = 6, | |||||
TopOverCostCount = 2000, | |||||
//MinSeqNumber = 1, | //MinSeqNumber = 1, | ||||
// MaxSeqNumber = 200, | // MaxSeqNumber = 200, | ||||
// BaseTime = DateTime.Now.AddYears(-10), | // BaseTime = DateTime.Now.AddYears(-10), | ||||
}; | }; | ||||
IIdGenerator IdGen = new DefaultIdGenerator(options); | |||||
IdGen = new DefaultIdGenerator(options); | |||||
GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId); | GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId); | ||||
// 首先测试一下 IdHelper 方法,获取单个Id | // 首先测试一下 IdHelper 方法,获取单个Id | ||||
@@ -52,10 +54,44 @@ namespace Yitter.OrgSystem.TestA | |||||
while (true) | while (true) | ||||
{ | { | ||||
Go(options); | |||||
Thread.Sleep(1000); // 每隔3秒执行一次Go | |||||
Console.WriteLine("Hello World! C#"); | |||||
RunSingle(); | |||||
// Go(options); | |||||
// RustDll(); | |||||
Thread.Sleep(1000); // 每隔1秒执行一次Go | |||||
} | |||||
} | |||||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||||
public static extern long NextId(); | |||||
private static void RustDll() | |||||
{ | |||||
int i = 0; | |||||
long id = 0; | |||||
DateTime start = DateTime.Now; | |||||
while (i < 50000) | |||||
{ | |||||
id = NextId(); | |||||
i++; | |||||
} | |||||
DateTime end = DateTime.Now; | |||||
Console.WriteLine("id:" + id); | |||||
Console.WriteLine($"+++++++++++C# call rust dll, gen 5W, total: {(end - start).TotalMilliseconds} ms"); | |||||
} | |||||
private static void RunSingle() | |||||
{ | |||||
DateTime start = DateTime.Now; | |||||
for (int i = 0; i < genIdCount; i++) | |||||
{ | |||||
var id = IdGen.NewLong(); | |||||
} | } | ||||
DateTime end = DateTime.Now; | |||||
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); | |||||
Interlocked.Increment(ref Program.Count); | |||||
} | } | ||||
private static void Go(IdGeneratorOptions options) | private static void Go(IdGeneratorOptions options) | ||||
@@ -332,7 +332,7 @@ namespace Yitter.IdGenerator | |||||
public virtual long NextId() | public virtual long NextId() | ||||
{ | { | ||||
lock (_SyncLock) | |||||
lock (_SyncLock) | |||||
{ | { | ||||
return _IsOverCost ? NextOverCostId() : NextNormalId(); | return _IsOverCost ? NextOverCostId() : NextNormalId(); | ||||
} | } | ||||
@@ -20,7 +20,6 @@ public class GenTest { | |||||
public void GenStart() { | public void GenStart() { | ||||
long start = System.currentTimeMillis(); | long start = System.currentTimeMillis(); | ||||
long id = 0; | long id = 0; | ||||
for (int i = 0; i < GenIdCount; i++) { | for (int i = 0; i < GenIdCount; i++) { | ||||
@@ -22,11 +22,9 @@ public class StartUp { | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
IdGeneratorOptions options = new IdGeneratorOptions(); | IdGeneratorOptions options = new IdGeneratorOptions(); | ||||
// options.TopOverCostCount = 10000; | |||||
options.WorkerIdBitLength = 6; | |||||
options.SeqBitLength = 6; | |||||
// options.WorkerIdBitLength = 6; | |||||
// options.SeqBitLength = 6; | |||||
// options.TopOverCostCount = 2000; | |||||
// options.MinSeqNumber = 5; | // options.MinSeqNumber = 5; | ||||
// options.MaxSeqNumber = 200; | // options.MaxSeqNumber = 200; | ||||
@@ -1,13 +1,5 @@ | |||||
# This file is automatically @generated by Cargo. | # This file is automatically @generated by Cargo. | ||||
# It is not intended for manual editing. | # It is not intended for manual editing. | ||||
[[package]] | |||||
name = "RS-SnowF" | |||||
version = "1.0.0" | |||||
dependencies = [ | |||||
"chrono", | |||||
"lazy_static", | |||||
] | |||||
[[package]] | [[package]] | ||||
name = "autocfg" | name = "autocfg" | ||||
version = "1.0.1" | version = "1.0.1" | ||||
@@ -96,3 +88,11 @@ name = "winapi-x86_64-pc-windows-gnu" | |||||
version = "0.4.0" | version = "0.4.0" | ||||
source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||||
[[package]] | |||||
name = "yitidgen" | |||||
version = "1.0.0" | |||||
dependencies = [ | |||||
"chrono", | |||||
"lazy_static", | |||||
] |
@@ -1,5 +1,5 @@ | |||||
[package] | [package] | ||||
name = "RS-SnowF" | |||||
name = "yitidgen" | |||||
version = "1.0.0" | version = "1.0.0" | ||||
authors = ["yitter <yitter@126.com>"] | authors = ["yitter <yitter@126.com>"] | ||||
edition = "2018" | edition = "2018" | ||||
@@ -10,3 +10,7 @@ edition = "2018" | |||||
chrono = "0.4.10" | chrono = "0.4.10" | ||||
lazy_static = "1.4.0" | lazy_static = "1.4.0" | ||||
[lib] | |||||
name = "yitidgen" | |||||
path = "./src/lib.rs" | |||||
crate-type = ["cdylib"] |
@@ -0,0 +1,15 @@ | |||||
mod yitgen; | |||||
use yitgen::gen::YitIdHelper; | |||||
use yitgen::contract::*; | |||||
// #[export_name = "SetIdGenerator"] | |||||
#[no_mangle] | |||||
pub extern "C" fn SetIdGenerator(options: IdGeneratorOptions) { | |||||
YitIdHelper::SetIdGenerator(options); | |||||
} | |||||
#[no_mangle] | |||||
pub extern "C" fn NextId() -> i64 { | |||||
YitIdHelper::NextId() | |||||
} | |||||
@@ -4,13 +4,17 @@ use yitgen::contract::*; | |||||
use yitgen::gen::*; | use yitgen::gen::*; | ||||
use std::thread; | use std::thread; | ||||
use chrono::Utc; | use chrono::Utc; | ||||
use std::sync::{Arc, Mutex}; | |||||
use std::time::Duration; | use std::time::Duration; | ||||
use std::ops::Deref; | |||||
fn main() { | fn main() { | ||||
println!("Hello, world! Rust"); | println!("Hello, world! Rust"); | ||||
// 总执行次数 | |||||
let times = 50000; | |||||
// 是否启用多线程测试 | |||||
let multiThread = false; | |||||
// 全局设置一次运行参数 | // 全局设置一次运行参数 | ||||
let mut options = IdGeneratorOptions::New(1); | let mut options = IdGeneratorOptions::New(1); | ||||
options.WorkerIdBitLength = 6; | options.WorkerIdBitLength = 6; | ||||
@@ -22,10 +26,9 @@ fn main() { | |||||
loop { | loop { | ||||
let mut i = 0; | let mut i = 0; | ||||
let mut id: i64 = 0; | let mut id: i64 = 0; | ||||
let multiThread = false; | |||||
let start = Utc::now().timestamp_millis(); | let start = Utc::now().timestamp_millis(); | ||||
while i < 50000 { | |||||
while i < times { | |||||
i += 1; | i += 1; | ||||
if multiThread { // 这是多线程 | if multiThread { // 这是多线程 | ||||
thread::spawn(move || { | thread::spawn(move || { | ||||
@@ -44,7 +47,7 @@ fn main() { | |||||
println!("单线程用时 {} ms", end - start); | println!("单线程用时 {} ms", end - start); | ||||
} | } | ||||
thread::sleep(std::time::Duration::from_millis(1000)); | |||||
thread::sleep(std::time::Duration::from_millis(2000)); | |||||
} | } | ||||
} | } | ||||
@@ -2,10 +2,6 @@ | |||||
* 版权属于:yitter(yitter@126.com) | * 版权属于:yitter(yitter@126.com) | ||||
* 开源地址:https://gitee.com/yitter/idgenerator | * 开源地址:https://gitee.com/yitter/idgenerator | ||||
*/ | */ | ||||
use std::{thread, time}; | |||||
use std::net::UdpSocket; | |||||
use std::sync::{Arc, Mutex}; | |||||
use chrono::Utc; | |||||
pub struct IdGeneratorOptions { | pub struct IdGeneratorOptions { | ||||
/// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | /// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 | ||||
@@ -13,7 +9,7 @@ pub struct IdGeneratorOptions { | |||||
/// 基础时间,不能超过当前系统时间 | /// 基础时间,不能超过当前系统时间 | ||||
pub BaseTime: i64, | pub BaseTime: i64, | ||||
/// 机器码,与 WorkerIdBitLength 有关系 | /// 机器码,与 WorkerIdBitLength 有关系 | ||||
pub WorkerId: u16, | |||||
pub WorkerId: u32, | |||||
/// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | /// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) | ||||
pub WorkerIdBitLength: u8, | pub WorkerIdBitLength: u8, | ||||
/// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | /// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) | ||||
@@ -27,7 +23,7 @@ pub struct IdGeneratorOptions { | |||||
} | } | ||||
impl IdGeneratorOptions { | impl IdGeneratorOptions { | ||||
pub fn New(workerId: u16) -> IdGeneratorOptions { | |||||
pub fn New(workerId: u32) -> IdGeneratorOptions { | |||||
return IdGeneratorOptions { | return IdGeneratorOptions { | ||||
Method: 1, | Method: 1, | ||||
WorkerId: workerId, | WorkerId: workerId, | ||||
@@ -5,18 +5,14 @@ | |||||
use super::super::contract::*; | use super::super::contract::*; | ||||
use std::{thread}; | use std::{thread}; | ||||
use chrono::Utc; | use chrono::Utc; | ||||
use std::sync::Mutex; | |||||
use std::sync::Arc; | |||||
use std::ops::Add; | |||||
use std::thread::sleep; | use std::thread::sleep; | ||||
use std::sync::mpsc::channel; | |||||
use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||
pub struct SnowWorkerM1 { | pub struct SnowWorkerM1 { | ||||
///基础时间 | ///基础时间 | ||||
pub BaseTime: i64, | pub BaseTime: i64, | ||||
///机器码 | ///机器码 | ||||
pub WorkerId: u16, | |||||
pub WorkerId: u32, | |||||
///机器码位长 | ///机器码位长 | ||||
pub WorkerIdBitLength: u8, | pub WorkerIdBitLength: u8, | ||||
///自增序列数位长 | ///自增序列数位长 | ||||
@@ -69,7 +65,7 @@ impl SnowWorkerM1 { | |||||
} | } | ||||
// WorkerId | // WorkerId | ||||
let maxWorkerIdNumber = (2 as u16).pow(options.WorkerIdBitLength as u32) - 1; | |||||
let maxWorkerIdNumber = (2 as u32).pow(options.WorkerIdBitLength as u32) - 1; | |||||
if options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber { | if options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber { | ||||
panic!("WorkerId error. (range:[0, {} ]", if maxWorkerIdNumber <= 0 { 63 } else { maxWorkerIdNumber }) | panic!("WorkerId error. (range:[0, {} ]", if maxWorkerIdNumber <= 0 { 63 } else { maxWorkerIdNumber }) | ||||
} else { | } else { | ||||
@@ -133,6 +129,7 @@ impl SnowWorkerM1 { | |||||
} | } | ||||
pub fn NextId(&mut self) -> i64 { | 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() } | ||||
} | } | ||||
@@ -155,6 +152,7 @@ impl SnowWorkerM1 { | |||||
if currentTimeTick > self._LastTimeTick { | if currentTimeTick > self._LastTimeTick { | ||||
self.EndOverCostAction(currentTimeTick); | self.EndOverCostAction(currentTimeTick); | ||||
self._LastTimeTick = currentTimeTick; | self._LastTimeTick = currentTimeTick; | ||||
self._CurrentSeqNumber = self.MinSeqNumber; | self._CurrentSeqNumber = self.MinSeqNumber; | ||||
self._IsOverCost = false; | self._IsOverCost = false; | ||||
@@ -166,6 +164,7 @@ impl SnowWorkerM1 { | |||||
if self._OverCostCountInOneTerm >= self.TopOverCostCount { | if self._OverCostCountInOneTerm >= self.TopOverCostCount { | ||||
self.EndOverCostAction(currentTimeTick); | self.EndOverCostAction(currentTimeTick); | ||||
self._LastTimeTick = self.GetNextTimeTick(); | self._LastTimeTick = self.GetNextTimeTick(); | ||||
self._CurrentSeqNumber = self.MinSeqNumber; | self._CurrentSeqNumber = self.MinSeqNumber; | ||||
self._IsOverCost = false; | self._IsOverCost = false; | ||||
@@ -196,6 +195,7 @@ impl SnowWorkerM1 { | |||||
if self._TurnBackTimeTick < 1 { | if self._TurnBackTimeTick < 1 { | ||||
self._TurnBackTimeTick = self._LastTimeTick - 1; | self._TurnBackTimeTick = self._LastTimeTick - 1; | ||||
self._TurnBackIndex += 1; | self._TurnBackIndex += 1; | ||||
// 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 | // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 | ||||
// 最多4次回拨(防止回拨重叠) | // 最多4次回拨(防止回拨重叠) | ||||
if self._TurnBackIndex > 4 { | if self._TurnBackIndex > 4 { | ||||
@@ -217,11 +217,13 @@ impl SnowWorkerM1 { | |||||
if currentTimeTick > self._LastTimeTick { | if currentTimeTick > self._LastTimeTick { | ||||
self._LastTimeTick = currentTimeTick; | self._LastTimeTick = currentTimeTick; | ||||
self._CurrentSeqNumber = self.MinSeqNumber; | self._CurrentSeqNumber = self.MinSeqNumber; | ||||
return self.CalcId(self._LastTimeTick); | return self.CalcId(self._LastTimeTick); | ||||
} | } | ||||
if self._CurrentSeqNumber > self.MaxSeqNumber { | if self._CurrentSeqNumber > self.MaxSeqNumber { | ||||
self.BeginOverCostAction(currentTimeTick); | self.BeginOverCostAction(currentTimeTick); | ||||
self._TermIndex += 1; | self._TermIndex += 1; | ||||
self._LastTimeTick += 1; | self._LastTimeTick += 1; | ||||
self._CurrentSeqNumber = self.MinSeqNumber; | self._CurrentSeqNumber = self.MinSeqNumber; | ||||
@@ -236,13 +238,17 @@ impl SnowWorkerM1 { | |||||
} | } | ||||
fn CalcId(&mut self, useTimeTick: i64) -> i64 { | 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; | self._CurrentSeqNumber += 1; | ||||
return result; | return result; | ||||
} | } | ||||
fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { | 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; | self._TurnBackTimeTick -= 1; | ||||
return result; | return result; | ||||
} | } | ||||
@@ -7,14 +7,13 @@ use super::super::core::*; | |||||
use super::*; | use super::*; | ||||
use std::sync::Mutex; | use std::sync::Mutex; | ||||
use std::sync::Arc; | use std::sync::Arc; | ||||
use lazy_static::lazy_static; | |||||
pub struct YitIdHelper; | pub struct YitIdHelper; | ||||
static mut idGenInstance: Option<Arc<Mutex<DefaultIdGenerator>>> = None; | static mut idGenInstance: Option<Arc<Mutex<DefaultIdGenerator>>> = None; | ||||
impl YitIdHelper { | impl YitIdHelper { | ||||
fn IdGenInstance() -> Arc<Mutex<DefaultIdGenerator>> { | fn IdGenInstance() -> Arc<Mutex<DefaultIdGenerator>> { | ||||
unsafe { | unsafe { | ||||
idGenInstance.get_or_insert_with(|| { | idGenInstance.get_or_insert_with(|| { | ||||
@@ -23,14 +22,12 @@ impl YitIdHelper { | |||||
} | } | ||||
} | } | ||||
pub fn SetIdGenerator(options: IdGeneratorOptions) { | pub fn SetIdGenerator(options: IdGeneratorOptions) { | ||||
let mut idgenArc = YitIdHelper::IdGenInstance(); | let mut idgenArc = YitIdHelper::IdGenInstance(); | ||||
let mut idgen = idgenArc.lock().unwrap(); | let mut idgen = idgenArc.lock().unwrap(); | ||||
idgen.Worker.SetOptions(options); | idgen.Worker.SetOptions(options); | ||||
} | } | ||||
#[no_mangle] | |||||
pub fn NextId() -> i64 { | pub fn NextId() -> i64 { | ||||
let mut idgenArc = YitIdHelper::IdGenInstance(); | let mut idgenArc = YitIdHelper::IdGenInstance(); | ||||
let mut idgen = idgenArc.lock().unwrap(); | let mut idgen = idgenArc.lock().unwrap(); | ||||