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