Skip to content

Commit ec27c19

Browse files
authored
chore: improve performance 20% in benchmark (#55)
1 parent 98466f1 commit ec27c19

File tree

2 files changed

+125
-71
lines changed

2 files changed

+125
-71
lines changed

benches/bench.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ fn bench_bool_toggle(pair: (&FeatureProbe, &FPUser)) {
77
let fp = pair.0;
88
let user = pair.1;
99

10-
let _d = fp.bool_detail("bool_toogle", user, false);
10+
let _d = fp.bool_value("bool_toggle", user, false);
11+
}
12+
13+
fn bench_bool_toggle_detail(pair: (&FeatureProbe, &FPUser)) {
14+
let fp = pair.0;
15+
let user = pair.1;
16+
17+
let _d = fp.bool_detail("bool_toggle", user, false);
1118
}
1219

1320
fn bench_json_toggle(pair: (&FeatureProbe, &FPUser)) {
1421
let fp = pair.0;
1522
let user = pair.1;
1623

17-
let _d = fp.json_detail("multi_condition_toggle", user, json!(""));
24+
let _d = fp.json_value("multi_condition_toggle", user, json!(""));
1825
}
1926

2027
fn criterion_benchmark(c: &mut Criterion) {
@@ -26,14 +33,18 @@ fn criterion_benchmark(c: &mut Criterion) {
2633
let user_hit = FPUser::new().with("city", "1");
2734
let fp = FeatureProbe::new_with("secret key".to_string(), repo);
2835

29-
c.bench_function("bench_bool_toggle_defualt", |b| {
36+
c.bench_function("bench_bool_toggle_default", |b| {
3037
b.iter(|| bench_bool_toggle(black_box((&fp, &user_default))))
3138
});
3239

3340
c.bench_function("bench_bool_toggle_hit", |b| {
3441
b.iter(|| bench_bool_toggle(black_box((&fp, &user_hit))))
3542
});
3643

44+
c.bench_function("bench_bool_toggle_detail_hit", |b| {
45+
b.iter(|| bench_bool_toggle_detail(black_box((&fp, &user_hit))))
46+
});
47+
3748
c.bench_function("bench_json_toggle_default", |b| {
3849
b.iter(|| bench_json_toggle(black_box((&fp, &user_default))))
3950
});

src/feature_probe.rs

Lines changed: 111 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -219,75 +219,27 @@ impl FeatureProbe {
219219
debug_until_time,
220220
)
221221
});
222-
let track_access_events = match repo.toggles.get(toggle) {
223-
Some(toggle) => toggle.track_access_events(),
224-
None => false,
225-
};
226-
let ts = unix_timestamp();
227-
self.record_access(toggle, user, track_access_events, &detail, ts);
228-
self.record_debug(toggle, user, debug_until_time, &detail, ts);
229-
if let Some(mut detail) = detail {
230-
detail.debug_until_time = debug_until_time;
231-
return Some(detail);
232-
}
233-
detail
234-
}
235-
236-
fn record_access(
237-
&self,
238-
toggle: &str,
239-
user: &FPUser,
240-
track_access_events: bool,
241-
detail: &Option<EvalDetail<Value>>,
242-
ts: u128,
243-
) -> Option<()> {
244-
let recorder = self.event_recorder.as_ref()?;
245-
let detail = detail.as_ref()?;
246-
let value = detail.value.as_ref()?;
247-
let event = AccessEvent {
248-
kind: "access".to_string(),
249-
time: ts,
250-
key: toggle.to_owned(),
251-
user: user.key(),
252-
value: value.clone(),
253-
variation_index: detail.variation_index.unwrap(),
254-
version: detail.version,
255-
rule_index: detail.rule_index,
256-
track_access_events,
257-
};
258-
recorder.record_event(Event::AccessEvent(event));
259-
None
260-
}
261222

262-
fn record_debug(
263-
&self,
264-
toggle: &str,
265-
user: &FPUser,
266-
debug_until_time: Option<u64>,
267-
detail: &Option<EvalDetail<Value>>,
268-
ts: u128,
269-
) -> Option<()> {
270-
let recorder = self.event_recorder.as_ref()?;
271-
let detail = detail.as_ref()?;
272-
let value = detail.value.as_ref()?;
273-
if let Some(debug_until_time) = debug_until_time {
274-
if debug_until_time as u128 >= ts {
275-
let debug = DebugEvent {
276-
kind: "debug".to_string(),
277-
time: ts,
278-
key: toggle.to_owned(),
279-
user: user.key(),
280-
user_detail: serde_json::to_value(user).unwrap(),
281-
value: value.clone(),
282-
variation_index: detail.variation_index.unwrap(),
283-
version: detail.version,
284-
rule_index: detail.rule_index,
285-
reason: Some(detail.reason.to_string()),
286-
};
287-
recorder.record_event(Event::DebugEvent(debug));
288-
}
223+
if let Some(recorder) = &self.event_recorder {
224+
let track_access_events = repo
225+
.toggles
226+
.get(toggle)
227+
.map(|t| t.track_access_events())
228+
.unwrap_or(false);
229+
record_event(
230+
recorder.clone(),
231+
track_access_events,
232+
toggle,
233+
user,
234+
detail.clone(),
235+
debug_until_time,
236+
)
289237
}
290-
None
238+
239+
detail.map(|mut d| {
240+
d.debug_until_time = debug_until_time;
241+
d
242+
})
291243
}
292244

293245
fn start(&mut self) {
@@ -408,6 +360,97 @@ impl FeatureProbe {
408360
}
409361
}
410362

363+
fn record_event(
364+
recorder: EventRecorder,
365+
track_access_events: bool,
366+
toggle: &str,
367+
user: &FPUser,
368+
detail: Option<EvalDetail<Value>>,
369+
debug_until_time: Option<u64>,
370+
) {
371+
let toggle = toggle.to_owned();
372+
let user = user.key();
373+
let user_detail = serde_json::to_value(user.clone()).unwrap_or_default();
374+
375+
tokio::spawn(async move {
376+
let ts = unix_timestamp();
377+
record_access(
378+
&recorder,
379+
&toggle,
380+
user.clone(),
381+
track_access_events,
382+
&detail,
383+
ts,
384+
);
385+
record_debug(
386+
&recorder,
387+
&toggle,
388+
user,
389+
user_detail,
390+
debug_until_time,
391+
&detail,
392+
ts,
393+
);
394+
});
395+
}
396+
397+
fn record_access(
398+
recorder: &EventRecorder,
399+
toggle: &str,
400+
user: String,
401+
track_access_events: bool,
402+
detail: &Option<EvalDetail<Value>>,
403+
ts: u128,
404+
) -> Option<()> {
405+
let detail = detail.as_ref()?;
406+
let value = detail.value.as_ref()?;
407+
let event = AccessEvent {
408+
kind: "access".to_string(),
409+
time: ts,
410+
key: toggle.to_owned(),
411+
user,
412+
value: value.clone(),
413+
variation_index: detail.variation_index?,
414+
version: detail.version,
415+
rule_index: detail.rule_index,
416+
track_access_events,
417+
};
418+
recorder.record_event(Event::AccessEvent(event));
419+
None
420+
}
421+
422+
#[allow(clippy::too_many_arguments)]
423+
fn record_debug(
424+
recorder: &EventRecorder,
425+
toggle: &str,
426+
user: String,
427+
user_detail: Value,
428+
debug_until_time: Option<u64>,
429+
detail: &Option<EvalDetail<Value>>,
430+
ts: u128,
431+
) -> Option<()> {
432+
let detail = detail.as_ref()?;
433+
let value = detail.value.as_ref()?;
434+
if let Some(debug_until_time) = debug_until_time {
435+
if debug_until_time as u128 >= ts {
436+
let debug = DebugEvent {
437+
kind: "debug".to_string(),
438+
time: ts,
439+
key: toggle.to_owned(),
440+
user,
441+
user_detail,
442+
value: value.clone(),
443+
variation_index: detail.variation_index?,
444+
version: detail.version,
445+
rule_index: detail.rule_index,
446+
reason: Some(detail.reason.to_string()),
447+
};
448+
recorder.record_event(Event::DebugEvent(debug));
449+
}
450+
}
451+
None
452+
}
453+
411454
#[cfg(test)]
412455
mod tests {
413456
use serde_json::json;
@@ -497,7 +540,7 @@ mod tests {
497540
}
498541

499542
#[test]
500-
fn test_feature_probe_track() {
543+
fn test_feature_probe_record_debug() {
501544
let json = load_local_json("resources/fixtures/repo.json");
502545
let mut repo = json.unwrap();
503546
repo.debug_until_time = Some(unix_timestamp() as u64 + 60 * 1000);

0 commit comments

Comments
 (0)