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
impl BitLayout
Sourcepub fn new(
timestamp_bits: u8,
machine_id_bits: u8,
node_id_bits: u8,
sequence_bits: u8,
) -> Result<Self, SnowflakeError>
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?
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}Sourcepub const fn timestamp_bits(&self) -> u8
pub const fn timestamp_bits(&self) -> u8
Returns the number of bits allocated to the timestamp.
Sourcepub const fn machine_id_bits(&self) -> u8
pub const fn machine_id_bits(&self) -> u8
Returns the number of bits allocated to the machine identifier.
Sourcepub const fn node_id_bits(&self) -> u8
pub const fn node_id_bits(&self) -> u8
Returns the number of bits allocated to the node identifier.
Sourcepub const fn sequence_bits(&self) -> u8
pub const fn sequence_bits(&self) -> u8
Returns the number of bits allocated to the sequence counter.
Sourcepub const fn max_sequence(&self) -> u32
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);Sourcepub const fn max_machine_id(&self) -> i64
pub const fn max_machine_id(&self) -> i64
Maximum allowed machine_id.
use snowflake_gen::BitLayout;
assert_eq!(BitLayout::default().max_machine_id(), 31);Sourcepub const fn max_node_id(&self) -> i64
pub const fn max_node_id(&self) -> i64
Maximum allowed node_id.
use snowflake_gen::BitLayout;
assert_eq!(BitLayout::default().max_node_id(), 31);Sourcepub const fn max_timestamp_millis(&self) -> i64
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.
Sourcepub fn max_ids_per_second(&self) -> u64
pub fn max_ids_per_second(&self) -> u64
Maximum IDs that can be generated per second across all nodes.