mirror of
https://github.com/servo/servo.git
synced 2025-07-16 20:03:39 +01:00
layout: Stop using Rayon in single-threaded mode (#37832)
In layout, some parts of the code were still using parallel iterators from Rayon even when single-thread layout was activated. This change modifies those parts to use non-parallel iterators when `LayoutContext::use_rayon` is not active. Testing: It's very hard to make an automated test for this, but I've manually verified this by building with tracing and observing that layout runs only on a single thread now when loading https://servo.org. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
da364f7a61
commit
647122d0f6
3 changed files with 197 additions and 144 deletions
|
@ -44,6 +44,90 @@ enum ModernContainerJob<'dom> {
|
||||||
TextRuns(Vec<ModernContainerTextRun<'dom>>),
|
TextRuns(Vec<ModernContainerTextRun<'dom>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'dom> ModernContainerJob<'dom> {
|
||||||
|
fn finish(
|
||||||
|
self,
|
||||||
|
builder: &ModernContainerBuilder,
|
||||||
|
anonymous_info: &LazyLock<NodeAndStyleInfo<'dom>, impl FnOnce() -> NodeAndStyleInfo<'dom>>,
|
||||||
|
) -> Option<ModernItem<'dom>> {
|
||||||
|
match self {
|
||||||
|
ModernContainerJob::TextRuns(runs) => {
|
||||||
|
let mut inline_formatting_context_builder =
|
||||||
|
InlineFormattingContextBuilder::new(builder.info);
|
||||||
|
for flex_text_run in runs.into_iter() {
|
||||||
|
inline_formatting_context_builder
|
||||||
|
.push_text(flex_text_run.text, &flex_text_run.info);
|
||||||
|
}
|
||||||
|
|
||||||
|
let inline_formatting_context = inline_formatting_context_builder.finish(
|
||||||
|
builder.context,
|
||||||
|
true, /* has_first_formatted_line */
|
||||||
|
false, /* is_single_line_text_box */
|
||||||
|
builder.info.style.to_bidi_level(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let block_formatting_context = BlockFormattingContext::from_block_container(
|
||||||
|
BlockContainer::InlineFormattingContext(inline_formatting_context),
|
||||||
|
);
|
||||||
|
let info: &NodeAndStyleInfo = anonymous_info;
|
||||||
|
let formatting_context = IndependentFormattingContext {
|
||||||
|
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
||||||
|
contents: IndependentFormattingContextContents::NonReplaced(
|
||||||
|
IndependentNonReplacedContents::Flow(block_formatting_context),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(ModernItem {
|
||||||
|
kind: ModernItemKind::InFlow,
|
||||||
|
order: 0,
|
||||||
|
box_slot: None,
|
||||||
|
formatting_context,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ModernContainerJob::ElementOrPseudoElement {
|
||||||
|
info,
|
||||||
|
display,
|
||||||
|
contents,
|
||||||
|
box_slot,
|
||||||
|
} => {
|
||||||
|
let is_abspos = info.style.get_box().position.is_absolutely_positioned();
|
||||||
|
|
||||||
|
// Text decorations are not propagated to any out-of-flow descendants. In addition,
|
||||||
|
// absolutes don't affect the size of ancestors so it is fine to allow descendent
|
||||||
|
// tables to resolve percentage columns.
|
||||||
|
let propagated_data = match is_abspos {
|
||||||
|
false => builder.propagated_data,
|
||||||
|
true => PropagatedBoxTreeData::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let formatting_context = IndependentFormattingContext::construct(
|
||||||
|
builder.context,
|
||||||
|
&info,
|
||||||
|
display.display_inside(),
|
||||||
|
contents,
|
||||||
|
propagated_data,
|
||||||
|
);
|
||||||
|
|
||||||
|
if is_abspos {
|
||||||
|
Some(ModernItem {
|
||||||
|
kind: ModernItemKind::OutOfFlow,
|
||||||
|
order: 0,
|
||||||
|
box_slot: Some(box_slot),
|
||||||
|
formatting_context,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(ModernItem {
|
||||||
|
kind: ModernItemKind::InFlow,
|
||||||
|
order: info.style.clone_order(),
|
||||||
|
box_slot: Some(box_slot),
|
||||||
|
formatting_context,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ModernContainerTextRun<'dom> {
|
struct ModernContainerTextRun<'dom> {
|
||||||
info: NodeAndStyleInfo<'dom>,
|
info: NodeAndStyleInfo<'dom>,
|
||||||
text: Cow<'dom, str>,
|
text: Cow<'dom, str>,
|
||||||
|
@ -137,84 +221,17 @@ impl<'a, 'dom> ModernContainerBuilder<'a, 'dom> {
|
||||||
.pseudo(self.context, PseudoElement::ServoAnonymousBox)
|
.pseudo(self.context, PseudoElement::ServoAnonymousBox)
|
||||||
.expect("Should always be able to construct info for anonymous boxes.")
|
.expect("Should always be able to construct info for anonymous boxes.")
|
||||||
});
|
});
|
||||||
let mut children: Vec<ModernItem> = std::mem::take(&mut self.jobs)
|
|
||||||
.into_par_iter()
|
|
||||||
.filter_map(|job| match job {
|
|
||||||
ModernContainerJob::TextRuns(runs) => {
|
|
||||||
let mut inline_formatting_context_builder =
|
|
||||||
InlineFormattingContextBuilder::new(self.info);
|
|
||||||
for flex_text_run in runs.into_iter() {
|
|
||||||
inline_formatting_context_builder
|
|
||||||
.push_text(flex_text_run.text, &flex_text_run.info);
|
|
||||||
}
|
|
||||||
|
|
||||||
let inline_formatting_context = inline_formatting_context_builder.finish(
|
let jobs = std::mem::take(&mut self.jobs);
|
||||||
self.context,
|
let mut children: Vec<_> = if self.context.use_rayon {
|
||||||
true, /* has_first_formatted_line */
|
jobs.into_par_iter()
|
||||||
false, /* is_single_line_text_box */
|
.filter_map(|job| job.finish(&self, &anonymous_info))
|
||||||
self.info.style.to_bidi_level(),
|
.collect()
|
||||||
)?;
|
} else {
|
||||||
|
jobs.into_iter()
|
||||||
let block_formatting_context = BlockFormattingContext::from_block_container(
|
.filter_map(|job| job.finish(&self, &anonymous_info))
|
||||||
BlockContainer::InlineFormattingContext(inline_formatting_context),
|
.collect()
|
||||||
);
|
};
|
||||||
let info: &NodeAndStyleInfo = &anonymous_info;
|
|
||||||
let formatting_context = IndependentFormattingContext {
|
|
||||||
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
|
||||||
contents: IndependentFormattingContextContents::NonReplaced(
|
|
||||||
IndependentNonReplacedContents::Flow(block_formatting_context),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(ModernItem {
|
|
||||||
kind: ModernItemKind::InFlow,
|
|
||||||
order: 0,
|
|
||||||
box_slot: None,
|
|
||||||
formatting_context,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
ModernContainerJob::ElementOrPseudoElement {
|
|
||||||
info,
|
|
||||||
display,
|
|
||||||
contents,
|
|
||||||
box_slot,
|
|
||||||
} => {
|
|
||||||
let is_abspos = info.style.get_box().position.is_absolutely_positioned();
|
|
||||||
|
|
||||||
// Text decorations are not propagated to any out-of-flow descendants. In addition,
|
|
||||||
// absolutes don't affect the size of ancestors so it is fine to allow descendent
|
|
||||||
// tables to resolve percentage columns.
|
|
||||||
let propagated_data = match is_abspos {
|
|
||||||
false => self.propagated_data,
|
|
||||||
true => PropagatedBoxTreeData::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let formatting_context = IndependentFormattingContext::construct(
|
|
||||||
self.context,
|
|
||||||
&info,
|
|
||||||
display.display_inside(),
|
|
||||||
contents,
|
|
||||||
propagated_data,
|
|
||||||
);
|
|
||||||
|
|
||||||
if is_abspos {
|
|
||||||
Some(ModernItem {
|
|
||||||
kind: ModernItemKind::OutOfFlow,
|
|
||||||
order: 0,
|
|
||||||
box_slot: Some(box_slot),
|
|
||||||
formatting_context,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(ModernItem {
|
|
||||||
kind: ModernItemKind::InFlow,
|
|
||||||
order: info.style.clone_order(),
|
|
||||||
box_slot: Some(box_slot),
|
|
||||||
formatting_context,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-flexbox/#order-modified-document-order
|
// https://drafts.csswg.org/css-flexbox/#order-modified-document-order
|
||||||
children.sort_by_key(|child| child.order);
|
children.sort_by_key(|child| child.order);
|
||||||
|
|
|
@ -1221,14 +1221,25 @@ impl InitialFlexLineLayout<'_> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-flexbox/#algo-cross-item
|
// https://drafts.csswg.org/css-flexbox/#algo-cross-item
|
||||||
let layout_results = items
|
let layout_results: Vec<_> = if flex_context.layout_context.use_rayon {
|
||||||
.par_iter()
|
items
|
||||||
.zip(&item_used_main_sizes)
|
.par_iter()
|
||||||
.map(|(item, used_main_size)| {
|
.zip(&item_used_main_sizes)
|
||||||
item.layout(*used_main_size, flex_context, None, None)
|
.map(|(item, used_main_size)| {
|
||||||
.unwrap()
|
item.layout(*used_main_size, flex_context, None, None)
|
||||||
})
|
.unwrap()
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
items
|
||||||
|
.iter()
|
||||||
|
.zip(&item_used_main_sizes)
|
||||||
|
.map(|(item, used_main_size)| {
|
||||||
|
item.layout(*used_main_size, flex_context, None, None)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
let items: Vec<_> = izip!(
|
let items: Vec<_> = izip!(
|
||||||
items.into_iter(),
|
items.into_iter(),
|
||||||
|
|
|
@ -1069,71 +1069,96 @@ impl<'a> TableLayout<'a> {
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_table: &ContainingBlock,
|
containing_block_for_table: &ContainingBlock,
|
||||||
) {
|
) {
|
||||||
self.cells_laid_out = self
|
let layout_table_slot = |coordinate: TableSlotCoordinates, slot: &TableSlot| {
|
||||||
.table
|
let TableSlot::Cell(cell) = slot else {
|
||||||
.slots
|
return None;
|
||||||
.par_iter()
|
};
|
||||||
.enumerate()
|
|
||||||
.map(|(row_index, row_slots)| {
|
|
||||||
row_slots
|
|
||||||
.par_iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(column_index, slot)| {
|
|
||||||
let TableSlot::Cell(cell) = slot else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
let cell = cell.borrow();
|
let cell = cell.borrow();
|
||||||
let area = LogicalSides {
|
let area = LogicalSides {
|
||||||
inline_start: column_index,
|
inline_start: coordinate.x,
|
||||||
inline_end: column_index + cell.colspan,
|
inline_end: coordinate.x + cell.colspan,
|
||||||
block_start: row_index,
|
block_start: coordinate.y,
|
||||||
block_end: row_index + cell.rowspan,
|
block_end: coordinate.y + cell.rowspan,
|
||||||
};
|
};
|
||||||
let layout_style = cell.layout_style();
|
let layout_style = cell.layout_style();
|
||||||
let border = self
|
let border = self
|
||||||
.get_collapsed_border_widths_for_area(area)
|
.get_collapsed_border_widths_for_area(area)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
layout_style
|
layout_style.border_width(containing_block_for_table.style.writing_mode)
|
||||||
.border_width(containing_block_for_table.style.writing_mode)
|
});
|
||||||
});
|
let padding: LogicalSides<Au> = layout_style
|
||||||
let padding: LogicalSides<Au> = layout_style
|
.padding(containing_block_for_table.style.writing_mode)
|
||||||
.padding(containing_block_for_table.style.writing_mode)
|
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
||||||
.percentages_relative_to(self.basis_for_cell_padding_percentage);
|
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
|
||||||
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
|
|
||||||
|
|
||||||
let mut total_cell_width: Au = (column_index..column_index + cell.colspan)
|
let mut total_cell_width: Au = (coordinate.x..coordinate.x + cell.colspan)
|
||||||
.map(|column_index| self.distributed_column_widths[column_index])
|
.map(|column_index| self.distributed_column_widths[column_index])
|
||||||
.sum::<Au>() -
|
.sum::<Au>() -
|
||||||
inline_border_padding_sum;
|
inline_border_padding_sum;
|
||||||
total_cell_width = total_cell_width.max(Au::zero());
|
total_cell_width = total_cell_width.max(Au::zero());
|
||||||
|
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
size: ContainingBlockSize {
|
size: ContainingBlockSize {
|
||||||
inline: total_cell_width,
|
inline: total_cell_width,
|
||||||
block: SizeConstraint::default(),
|
block: SizeConstraint::default(),
|
||||||
},
|
},
|
||||||
style: &cell.base.style,
|
style: &cell.base.style,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut positioning_context = PositioningContext::default();
|
let mut positioning_context = PositioningContext::default();
|
||||||
let layout = cell.contents.layout(
|
let layout = cell.contents.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
&mut positioning_context,
|
&mut positioning_context,
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
false, /* depends_on_block_constraints */
|
false, /* depends_on_block_constraints */
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(CellLayout {
|
Some(CellLayout {
|
||||||
layout,
|
layout,
|
||||||
padding,
|
padding,
|
||||||
border,
|
border,
|
||||||
positioning_context,
|
positioning_context,
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
})
|
})
|
||||||
.collect();
|
};
|
||||||
|
|
||||||
|
self.cells_laid_out = if layout_context.use_rayon {
|
||||||
|
self.table
|
||||||
|
.slots
|
||||||
|
.par_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(row_index, row_slots)| {
|
||||||
|
row_slots
|
||||||
|
.par_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(column_index, slot)| {
|
||||||
|
layout_table_slot(
|
||||||
|
TableSlotCoordinates::new(column_index, row_index),
|
||||||
|
slot,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
self.table
|
||||||
|
.slots
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(row_index, row_slots)| {
|
||||||
|
row_slots
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(column_index, slot)| {
|
||||||
|
layout_table_slot(
|
||||||
|
TableSlotCoordinates::new(column_index, row_index),
|
||||||
|
slot,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
// Now go through all cells laid out and update the cell measure based on the size
|
// Now go through all cells laid out and update the cell measure based on the size
|
||||||
// determined during layout.
|
// determined during layout.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue