| @@ -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(); | |||