dag: add another fast path for IdSet::push

Summary:
Partially address a PERF comment. The path would be useful in upcoming changes.

`cargo bench --bench spanset` now shows:

  push_span (middle)                                  0.710 ms

Previously it was:

  push_span (middle)                                  5.750 ms

Note the difference will be larger if the IdSet contains more spans.
Practically, we are thinking about 10k spans scale.

Reviewed By: DurhamG

Differential Revision: D31708352

fbshipit-source-id: cccbbab80fb997a50d5cc2536b076ad604f9b8fe
This commit is contained in:
Jun Wu 2021-10-26 15:42:43 -07:00 committed by Facebook GitHub Bot
parent 53340d92a7
commit 563a73b7e3

View File

@ -626,9 +626,50 @@ impl SpanSet {
}
}
{
// PERF: There is a better way to do this by bisecting
// spans and insert in-place. For now, this code path is
// rarely used.
// Fast path: modify a span in-place.
// higher H1---->L1 cur H2---->L2 lower H3---->L3
// safe range L1-2---------------->H3+2
// Exceeding the safe range would cause spans to overlap and this path cannot
// handle that.
let idx = match self
.spans
.bsearch_by(|probe| (span.high + 1).cmp(&probe.low))
{
Ok(idx) => idx,
Err(idx) => idx,
};
for idx in [idx] {
if let Some(cur) = self.spans.get(idx) {
// Not overlap with span?
if span.high + 1 < cur.low || cur.high + 1 < span.low {
continue;
}
// Might merge with a higher span? (Not in safe range)
if idx > 0 {
if let Some(higher) = self.spans.get(idx - 1) {
if span.high + 1 >= higher.low {
continue;
}
}
}
// Might merge with a lower span? (Not in safe range)
if let Some(lower) = self.spans.get(idx + 1) {
if lower.high + 1 >= span.low {
continue;
}
}
// Passed all checks. Merge the span.
let mut cur = &mut self.spans[idx];
cur.high = cur.high.max(span.high);
cur.low = cur.low.min(span.low);
return;
}
}
}
{
// PERF: There might be a better way to do this by bisecting
// spans and insert or delete in-place. For now, this code
// path remains not optimized since it is rarely used.
*self = self.union(&SpanSet::from(span))
}
}