// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use std::sync::Arc;
const NUM_TILE_BUCKETS: usize = 6;
/// A pool of blob tile buffers to mitigate the overhead of /// allocating and deallocating blob tiles. /// /// The pool keeps a strong reference to each allocated buffers and /// reuses the ones with a strong count of 1. pubstruct BlobTilePool {
largest_size_class: usize,
buckets: [Vec<Arc<Vec<u8>>>; NUM_TILE_BUCKETS],
}
impl BlobTilePool { pubfn new() -> Self { // The default max tile size is actually 256, using 512 here // so that this still works when experimenting with larger // tile sizes. If we ever make larger adjustments, the buckets // should be changed accordingly. let max_tile_size = 512;
BlobTilePool {
largest_size_class: max_tile_size * max_tile_size * 4,
buckets: [
Vec::with_capacity(32),
Vec::with_capacity(32),
Vec::with_capacity(32),
Vec::with_capacity(32),
Vec::with_capacity(32),
Vec::with_capacity(32),
],
}
}
/// Get or allocate a tile buffer of the requested size. /// /// The returned buffer is zero-inizitalized. /// The length of the returned buffer is equal to the requested size, /// however the buffer may be allocated with a larger capacity to /// conform to the pool's corresponding bucket tile size. pubfn get_buffer(&mutself, requested_size: usize) -> MutableTileBuffer { if requested_size > self.largest_size_class { // If the requested size is larger than the largest size class, // simply return a MutableBuffer that isn't tracked/recycled by // the pool. // In Firefox this should only happen in pathological cases // where the blob visible area ends up so large that the tile // size is increased to avoid producing too many tiles. // See wr_resource_updates_add_blob_image. letmut buf = vec![0; requested_size]; return MutableTileBuffer {
ptr: buf.as_mut_ptr(),
strong_ref: Arc::new(buf),
};
}
let (bucket_idx, cap) = self.bucket_and_size(requested_size); let bucket = &mutself.buckets[bucket_idx]; letmut selected_idx = None; for (buf_idx, buffer) in bucket.iter().enumerate() { if Arc::strong_count(buffer) == 1 {
selected_idx = Some(buf_idx); break;
}
}
let ptr; let strong_ref; iflet Some(idx) = selected_idx {
{ // This works because we just ensured the pool has the only strong // ref to the buffer. let buffer = Arc::get_mut(&mut bucket[idx]).unwrap();
debug_assert!(buffer.capacity() >= requested_size); // Ensure the length is equal to the requested size. It's not // strictly necessay for the tile pool but the texture upload // code relies on it. unsafe { buffer.set_len(requested_size); }
// zero-initialize
buffer.fill(0);
ptr = buffer.as_mut_ptr();
}
strong_ref = Arc::clone(&bucket[idx]);
} else { // Allocate a buffer with the adequate capacity for the requested // size's bucket. letmut buf = vec![0; cap]; // Force the length to be the requested size. unsafe { buf.set_len(requested_size) };
ptr = buf.as_mut_ptr();
strong_ref = Arc::new(buf); // Track the new buffer.
bucket.push(Arc::clone(&strong_ref));
};
/// Go over all allocated tile buffers. For each bucket, deallocate some buffers /// until the number of unused buffer is more than half of the buffers for that /// bucket. /// /// In practice, if called regularly, this gradually lets go of blob tiles when /// they are not used. pubfn cleanup(&mutself) { for bucket in &mutself.buckets { let threshold = bucket.len() / 2; letmut num_available = 0;
bucket.retain(&mut |buffer: &Arc<Vec<u8>>| { if Arc::strong_count(buffer) > 1 { returntrue;
}
// The role of tile buffer is to encapsulate an Arc to the underlying buffer // with a reference count of at most 2 and a way to view the buffer's content // as a mutable slice, even though the reference count may be more than 1. // The safety of this relies on the other strong reference being held by the // tile pool which never accesses the buffer's content, so the only reference // that can access it is the `TileBuffer` itself. pubstruct MutableTileBuffer {
strong_ref: Arc<Vec<u8>>,
ptr: *mut u8,
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.