mirror of
https://github.com/lexmount/moli.git
synced 2026-10-08 16:01:05 +00:00
fix(renderer): escalate isolate maintenance under pressure
This commit is contained in:
@@ -29,9 +29,10 @@ const ACTIVE_PAGE_MODERATE_MEMORY_PRESSURE_PERIOD: Duration = Duration::from_sec
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(super) enum RendererOwnerMaintenanceAction {
|
||||
/// Ask V8 to perform its moderate-memory-pressure maintenance for the
|
||||
/// isolate currently attached to this Page.
|
||||
ModerateMemoryPressure,
|
||||
/// Ask V8 to perform memory-pressure maintenance for the isolate currently
|
||||
/// attached to this Page. The isolate selects moderate or critical
|
||||
/// pressure from its current heap occupancy.
|
||||
MemoryPressure,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
@@ -102,7 +103,7 @@ impl RendererPageOwnerMaintenanceResidence {
|
||||
};
|
||||
Some(RendererOwnerMaintenanceTask {
|
||||
token,
|
||||
action: RendererOwnerMaintenanceAction::ModerateMemoryPressure,
|
||||
action: RendererOwnerMaintenanceAction::MemoryPressure,
|
||||
scheduled_for: deadline,
|
||||
})
|
||||
}
|
||||
@@ -143,11 +144,11 @@ pub(super) async fn execute_owner_maintenance_task_on_local_lane(
|
||||
run_entry_on_bound_owner_local_store_local_task(local_executor, entry, move |entry| {
|
||||
Box::pin(async move {
|
||||
match task.action() {
|
||||
RendererOwnerMaintenanceAction::ModerateMemoryPressure => entry
|
||||
RendererOwnerMaintenanceAction::MemoryPressure => entry
|
||||
.page_vm_mut()
|
||||
.vm_mut()
|
||||
.renderer_document_isolate_ops()
|
||||
.notify_renderer_document_isolate_moderate_memory_pressure(),
|
||||
.notify_renderer_document_isolate_memory_pressure(),
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -53,6 +53,17 @@ use url::Url;
|
||||
|
||||
pub(crate) type ScriptVmBootstrapError = Box<(anyhow::Error, DomHost)>;
|
||||
|
||||
fn renderer_document_isolate_critical_pressure_required(
|
||||
used_heap_size: usize,
|
||||
heap_size_limit: usize,
|
||||
) -> bool {
|
||||
if heap_size_limit == 0 {
|
||||
return false;
|
||||
}
|
||||
let critical_threshold = heap_size_limit / 3 + usize::from(!heap_size_limit.is_multiple_of(3));
|
||||
used_heap_size >= critical_threshold
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn expect_ready_child_frame_owner_source_future_for_test<F>(future: F) -> F::Output
|
||||
where
|
||||
@@ -6742,10 +6753,24 @@ impl ScriptVm {
|
||||
})
|
||||
}
|
||||
|
||||
fn notify_renderer_document_isolate_moderate_memory_pressure(&mut self) -> Result<()> {
|
||||
fn notify_renderer_document_isolate_memory_pressure(&mut self) -> Result<()> {
|
||||
self.renderer_document_isolate
|
||||
.with_entered_renderer_document_isolate(|isolate| {
|
||||
isolate.memory_pressure_notification(v8::MemoryPressureLevel::Moderate);
|
||||
let stats = isolate.get_heap_statistics();
|
||||
if renderer_document_isolate_critical_pressure_required(
|
||||
stats.used_heap_size(),
|
||||
stats.heap_size_limit(),
|
||||
) {
|
||||
// One renderer process can host several Page isolates. A
|
||||
// target with a rapidly replaced child realm must not hit
|
||||
// V8's process-fatal heap limit before its owner can close
|
||||
// that target. Escalate the existing periodic maintenance
|
||||
// once this isolate consumes a third of its own limit.
|
||||
isolate.memory_pressure_notification(v8::MemoryPressureLevel::Critical);
|
||||
isolate.low_memory_notification();
|
||||
} else {
|
||||
isolate.memory_pressure_notification(v8::MemoryPressureLevel::Moderate);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -6821,11 +6846,8 @@ impl ScriptVmRendererDocumentIsolateOps<'_> {
|
||||
self.vm.collect_renderer_document_isolate_garbage()
|
||||
}
|
||||
|
||||
pub(super) fn notify_renderer_document_isolate_moderate_memory_pressure(
|
||||
&mut self,
|
||||
) -> Result<()> {
|
||||
self.vm
|
||||
.notify_renderer_document_isolate_moderate_memory_pressure()
|
||||
pub(super) fn notify_renderer_document_isolate_memory_pressure(&mut self) -> Result<()> {
|
||||
self.vm.notify_renderer_document_isolate_memory_pressure()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::{
|
||||
PostParseProcessingAction, PostParseRuntimeDriverStep, PostParseStageBoundary,
|
||||
PostParseTaskCompletion, PostParseTaskExecutionToken, PostParseTaskInvalidationPolicy,
|
||||
ReadyPostParseAction, ScriptVm, ScriptVmDefaultWorldBootstrap, StandaloneScriptVmHarness,
|
||||
select_post_parse_driver_step,
|
||||
renderer_document_isolate_critical_pressure_required, select_post_parse_driver_step,
|
||||
};
|
||||
use crate::document_runtime::{
|
||||
CurrentScriptContextSpec, DeferredPageTask, DeferredPageTaskLane, DeferredPageTaskState,
|
||||
@@ -5193,6 +5193,20 @@ fn dom_wrapper_expando_survives_renderer_document_isolate_garbage_collection() {
|
||||
assert_eq!(retained, "retained");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renderer_document_isolate_memory_pressure_escalates_at_one_third_of_heap_limit() {
|
||||
assert!(!renderer_document_isolate_critical_pressure_required(0, 0));
|
||||
assert!(!renderer_document_isolate_critical_pressure_required(
|
||||
33, 100
|
||||
));
|
||||
assert!(renderer_document_isolate_critical_pressure_required(
|
||||
34, 100
|
||||
));
|
||||
assert!(renderer_document_isolate_critical_pressure_required(
|
||||
100, 100
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_wrapper_cache_is_cleared_on_script_vm_teardown() {
|
||||
let mut vm = new_parsed_test_vm(
|
||||
|
||||
Reference in New Issue
Block a user