Skip to content

Commit ecdbe72

Browse files
committed
DO NOT MERGE: pessimize solx-evm-assembly block map to test the summary
Replaces the per-function block BTreeMap with a flat Vec kept sorted by key, so lookups (get_mut during traversal) and find-or-insert degrade from O(log n) to linear scans, i.e. O(n^2) block construction. This is a realistic algorithmic compile-time regression, not a synthetic sleep, for validating the integration benchmark summary against real data. Order is preserved (the Vec stays sorted), so emission order and generated bytecode are unchanged; only compile time regresses. Bounded by the EVM 24 KB code-size limit on per-function block counts, so it stays well inside the 300-minute job timeout. Revert before merging.
1 parent b28085e commit ecdbe72

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

  • solx-evm-assembly/src/ethereal_ir/function

solx-evm-assembly/src/ethereal_ir/function/mod.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ pub struct Function {
5252
/// The optional code segment. Only used for the EVM target.
5353
pub code_segment: solx_utils::CodeSegment,
5454
/// The separately labelled blocks.
55-
pub blocks: BTreeMap<solx_codegen_evm::BlockKey, Vec<Block>>,
55+
///
56+
/// DUMMY BENCHMARK PROBE, DO NOT MERGE. This was a `BTreeMap` keyed by
57+
/// block; it is now a flat vector kept sorted by key so lookups degrade to
58+
/// linear scans, giving the PR toolchain a real compile-time regression for
59+
/// the integration summary to report. Restore the `BTreeMap` before merging.
60+
pub blocks: Vec<(solx_codegen_evm::BlockKey, Vec<Block>)>,
5661
/// The function type.
5762
pub r#type: Type,
5863
/// The function stack size.
@@ -84,7 +89,7 @@ impl Function {
8489
solc_version,
8590
name,
8691
code_segment,
87-
blocks: BTreeMap::new(),
92+
blocks: Vec::new(),
8893
r#type,
8994
stack_size: 0,
9095
capture_stacks,
@@ -169,8 +174,9 @@ impl Function {
169174
if let Some(&instance) = visited_blocks.get(&visited_element) {
170175
if let Some(predecessor) = queue_element.predecessor.take() {
171176
self.blocks
172-
.get_mut(&queue_element.block_key)
173-
.and_then(|instances| instances.get_mut(instance))
177+
.iter_mut()
178+
.find(|(key, _)| key == &queue_element.block_key)
179+
.and_then(|(_, instances)| instances.get_mut(instance))
174180
.expect("Always exists")
175181
.insert_predecessor(predecessor.0, predecessor.1);
176182
}
@@ -1387,7 +1393,20 @@ impl Function {
13871393
/// Pushes a block into the function.
13881394
///
13891395
fn insert_block(&mut self, mut block: Block) -> &mut Block {
1390-
let instances = self.blocks.entry(block.key.clone()).or_default();
1396+
let index = match self.blocks.iter().position(|(key, _)| key == &block.key) {
1397+
Some(index) => index,
1398+
None => {
1399+
let insert_at = self
1400+
.blocks
1401+
.iter()
1402+
.position(|(key, _)| key > &block.key)
1403+
.unwrap_or(self.blocks.len());
1404+
self.blocks
1405+
.insert(insert_at, (block.key.clone(), Vec::new()));
1406+
insert_at
1407+
}
1408+
};
1409+
let instances = &mut self.blocks[index].1;
13911410
block.instance = Some(instances.len());
13921411
instances.push(block);
13931412
instances.last_mut().expect("Always exists")

0 commit comments

Comments
 (0)