본문으로 건너뛰기

Chromium Memory Management and Tile Priority

Memory Budget

The compositor uses a soft/hard memory limit system rather than limiting the count of tiles or textures.

Limits

LimitDefaultPurpose
bytes_limit_when_visible64 MBInitial memory budget for visible tabs
num_resources_limit10,000,000Effectively unlimited; memory is the real gate
max_staging_buffer_usage_in_bytes32 MBFor one-copy raster staging buffers

The soft memory limit is hard_limit * max_memory_for_prepaint_percentage / 100 (default 100%, meaning soft = hard in the default configuration).

Source: cc/trees/layer_tree_settings.cc, cc/resources/managed_memory_policy.cc

Memory Policy Tiers

The system operates under one of four memory policies:

PolicyWhat gets memory
ALLOW_NOTHINGInvisible tabs — all tiles evicted
ALLOW_ABSOLUTE_MINIMUMOnly NOW-priority tiles
ALLOW_PREPAINT_ONLYNOW + SOON tiles
ALLOW_ANYTHINGAll tiles including EVENTUALLY

The policy is set based on tab visibility and system memory pressure.

Source: cc/tiles/tile_priority.h

Eviction

When memory exceeds the budget, TileManager::AssignGpuMemoryToTiles() iterates the raster queue in priority order and stops scheduling when the memory limit is reached. Tiles that don't fit get OOM_MODE and are not rasterized.

NOW-priority tiles use the hard memory limit. SOON and EVENTUALLY tiles use the soft limit (which can be smaller).

Source: cc/tiles/tile_manager.cc

Tile Priority System

Priority Bins

Each tile is assigned to one of three priority bins based on spatial proximity to the viewport:

BinMeaning
NOWCurrently visible in the viewport
SOONIn the skewport or border region (will be visible soon)
EVENTUALLYIn the larger interest area (might become visible)

Spatial Priority Regions

The tiling computes several priority rectangles:

VISIBLE_RECT — the current viewport in tile coordinates. Tiles here get NOW priority.

SKEWPORT_RECT — a velocity-extrapolated rectangle that predicts where the user will scroll. Computed by taking the scroll velocity and projecting it forward by a configurable target time. Tiles here get SOON priority.

SOON_BORDER_RECT — a border (default ~15%) around the visible rect. Also SOON priority. Covers small movements and direction uncertainty.

EVENTUALLY_RECT — a larger padding area. Tiles here get EVENTUALLY priority and are rasterized only if memory allows.

Source: cc/tiles/picture_layer_tiling.cc

Distance Tiebreaker

Within the same priority bin, tiles are sorted by distance_to_visible (Manhattan distance from the tile to the nearest edge of the visible rect). Closer tiles are rasterized first.

Source: cc/tiles/tile_priority.h (IsHigherPriorityThan)

Iteration Order: Spiral From Center

Within each priority region, tiles are visited using TilingData::SpiralDifferenceIterator, which spirals outward from the visible rect center. This naturally processes viewport-edge tiles before far-away tiles.

Source: cc/tiles/tiling_set_raster_queue_all.h

Resource Pooling

ResourcePool

The ResourcePool manages GPU resources (SharedImages) for tiles. Key behaviors:

Acquisition: When a tile needs a resource, AcquireResource() first searches for a recycled resource matching the size, format, and color space. If none exists, a new SharedImage is created.

Non-exact reuse: Resources can be reused even if the size doesn't exactly match, as long as the recycled resource's area is within 2x of the requested area (kReuseThreshold = 2.0f).

Expiration: Unused resources expire after 5 seconds (kDefaultExpirationDelay). A background task periodically sweeps and releases expired resources.

No atlas: Each resource is an individual GPU texture. There is no texture atlas or packing.

Source: cc/resources/resource_pool.cc, cc/resources/resource_pool.h

Idle Cleanup

After frames stop being produced:

  • ScheduleReduceTileMemoryWhenIdle() — after 5 minutes, evicts all tiles below NOW priority
  • TrimPrepaintTiles() — evicts EVENTUALLY-bin tiles that haven't been used recently

Source: cc/tiles/tile_manager.cc