use std::alloc::GlobalAlloc;
use std::alloc::Layout;
use std::alloc::System;
use std::hint::black_box;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use cheetah_string::CheetahString;
use rocketmq_model::common::message::broker_message::BrokerMessage;
use rocketmq_model::common::message::message_envelope::MessageEnvelope;
use rocketmq_model::common::message::MessageTrait;
struct CountingAllocator;
static ALLOCATIONS: AtomicUsize = AtomicUsize::new(0);
unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATIONS.fetch_add(1, Ordering::Relaxed);
unsafe { System.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
}
#[global_allocator]
static GLOBAL: CountingAllocator = CountingAllocator;
fn allocations_for<R>(operation: impl FnOnce() -> R) -> usize {
ALLOCATIONS.store(0, Ordering::Relaxed);
let result = operation();
black_box(&result);
ALLOCATIONS.load(Ordering::Relaxed)
}
fn broker_message_with_properties() -> BrokerMessage {
let mut envelope = MessageEnvelope::default();
envelope.put_property(
CheetahString::from_static_str("KEYS"),
CheetahString::from_static_str("order-1001"),
);
envelope.put_property(
CheetahString::from_static_str("TAGS"),
CheetahString::from_static_str("paid"),
);
BrokerMessage::from_envelope(envelope)
}
#[test]
fn broker_message_property_lookup_allocation_baseline_is_bounded() {
let broker_message = broker_message_with_properties();
let existing_key_allocations = allocations_for(|| broker_message.property(black_box("KEYS")));
let missing_key_allocations = allocations_for(|| broker_message.property(black_box("NOT_EXISTS")));
assert_eq!(
existing_key_allocations, 0,
"existing key lookup allocated {existing_key_allocations} times"
);
assert_eq!(
missing_key_allocations, 0,
"missing key lookup allocated {missing_key_allocations} times"
);
}