Skip to main content

BitLayout

Struct BitLayout 

Source
pub struct BitLayout { /* private fields */ }
Expand description

Describes how the 63 usable bits of an i64 snowflake ID are partitioned.

All four fields must sum to exactly 63. The sign bit is reserved so that all generated IDs are positive and can be stored in signed integer columns without surprises.

§Field ordering (MSB → LSB)

[sign(1)] [timestamp(T)] [machine_id(M)] [node_id(N)] [sequence(S)]

§Example

use snowflake_gen::BitLayout;

// Classic Twitter layout
let layout = BitLayout::default();
assert_eq!(layout.max_sequence(), 4095);
assert_eq!(layout.max_machine_id(), 31);
assert_eq!(layout.max_node_id(), 31);

Implementations§

Source§

impl BitLayout

Source

pub fn new( timestamp_bits: u8, machine_id_bits: u8, node_id_bits: u8, sequence_bits: u8, ) -> Result<Self, SnowflakeError>

Creates a validated BitLayout.

Returns SnowflakeError::InvalidBitLayout if the four bit widths do not sum to exactly 63.

§Example
use snowflake_gen::BitLayout;

let layout = BitLayout::new(41, 5, 5, 12).unwrap(); // classic Twitter
let bad    = BitLayout::new(40, 5, 5, 12);          // sums to 62 → error
assert!(bad.is_err());
Examples found in repository?
examples/benchmark.rs (line 9)
7fn main() {
8    // 1. Initialize for a machine with a 5/5 sub-node layout (32 threads)
9    let layout = BitLayout::new(41, 5, 5, 12).unwrap();
10    init(1, layout).expect("could not initialize global snowflake");
11
12    println!("Starting benchmark with 32 threads...");
13    let thread_count = 32;
14    let iterations_per_thread = 1_000_000;
15
16    let counter = Arc::new(AtomicU64::new(0));
17    let start = Instant::now();
18
19    let handles: Vec<_> = (0..thread_count)
20        .map(|_| {
21            let cnt = Arc::clone(&counter);
22            thread::spawn(move || {
23                let mut local_count = 0;
24                for _ in 0..iterations_per_thread {
25                    if let Ok(_) = next_id() {
26                        local_count += 1;
27                    }
28                }
29                cnt.fetch_add(local_count, Ordering::Relaxed);
30            })
31        })
32        .collect();
33
34    for h in handles {
35        h.join().unwrap();
36    }
37
38    let duration = start.elapsed();
39    let total_ids = counter.load(Ordering::Relaxed);
40    let ids_per_sec = total_ids as f64 / duration.as_secs_f64();
41
42    println!("Generated {} IDs in {:?}", total_ids, duration);
43    println!(
44        "Throughput: {:.2} million IDs / sec",
45        ids_per_sec / 1_000_000.0
46    );
47}
Source

pub const fn timestamp_bits(&self) -> u8

Returns the number of bits allocated to the timestamp.

Source

pub const fn machine_id_bits(&self) -> u8

Returns the number of bits allocated to the machine identifier.

Source

pub const fn node_id_bits(&self) -> u8

Returns the number of bits allocated to the node identifier.

Source

pub const fn sequence_bits(&self) -> u8

Returns the number of bits allocated to the sequence counter.

Source

pub const fn max_sequence(&self) -> u32

Maximum allowed sequence value (IDs per millisecond − 1).

use snowflake_gen::BitLayout;
assert_eq!(BitLayout::default().max_sequence(), 4095);
Source

pub const fn max_machine_id(&self) -> i64

Maximum allowed machine_id.

use snowflake_gen::BitLayout;
assert_eq!(BitLayout::default().max_machine_id(), 31);
Source

pub const fn max_node_id(&self) -> i64

Maximum allowed node_id.

use snowflake_gen::BitLayout;
assert_eq!(BitLayout::default().max_node_id(), 31);
Source

pub const fn max_timestamp_millis(&self) -> i64

Maximum milliseconds the timestamp field can represent.

With 41 timestamp bits this is ~69 years from epoch.

Source

pub fn max_ids_per_second(&self) -> u64

Maximum IDs that can be generated per second across all nodes.

Trait Implementations§

Source§

impl Clone for BitLayout

Source§

fn clone(&self) -> BitLayout

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BitLayout

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BitLayout

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for BitLayout

Source§

fn eq(&self, other: &BitLayout) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for BitLayout

Source§

impl Eq for BitLayout

Source§

impl StructuralPartialEq for BitLayout

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.