aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-06-10 16:53:55 -0600
committerbors-servo <metajack+bors@gmail.com>2015-06-10 16:53:55 -0600
commitfdeebf86a1424e9fffa122efa08fe397f6e7cd7d (patch)
tree19bd89786b1bbc25a567d0f94b1633b347bff797 /components
parent752e03a502413f21cfb30e55d68110c50e034da6 (diff)
parent1553fada53115f58c86113b43b799615f4025b08 (diff)
downloadservo-fdeebf86a1424e9fffa122efa08fe397f6e7cd7d.tar.gz
servo-fdeebf86a1424e9fffa122efa08fe397f6e7cd7d.zip
Auto merge of #6309 - nnethercote:instrument-freetype, r=glennw
This will allow reporting of memory usage by FreeType instances, which are measured in the MiBs for LayoutWorker threads. This change also makes FreeType allocations happen with jemalloc instead of the system malloc, which is a good thing. Finally, the change documents some dubiousness involving FontContextHandle. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6309) <!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r--components/gfx/font_context.rs8
-rw-r--r--components/gfx/lib.rs1
-rw-r--r--components/gfx/platform/freetype/font_context.rs81
-rw-r--r--components/gfx/platform/macos/font_context.rs8
4 files changed, 85 insertions, 13 deletions
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
index 4201e2ddc5f..27ba6c493df 100644
--- a/components/gfx/font_context.rs
+++ b/components/gfx/font_context.rs
@@ -16,6 +16,7 @@ use platform::font_template::FontTemplateData;
use smallvec::SmallVec8;
use util::cache::HashCache;
use util::geometry::Au;
+use util::mem::HeapSizeOf;
use std::borrow::{self, ToOwned};
use std::cell::RefCell;
@@ -285,6 +286,13 @@ impl FontContext {
}
}
+impl HeapSizeOf for FontContext {
+ fn heap_size_of_children(&self) -> usize {
+ // FIXME(njn): Measure other fields eventually.
+ self.platform_handle.heap_size_of_children()
+ }
+}
+
struct LayoutFontGroupCacheKey {
pointer: Arc<SpecifiedFontStyle>,
size: Au,
diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs
index 9465fcc871f..3117c8f7a6d 100644
--- a/components/gfx/lib.rs
+++ b/components/gfx/lib.rs
@@ -16,6 +16,7 @@
#[macro_use]
extern crate log;
+extern crate alloc;
extern crate azure;
#[macro_use] extern crate bitflags;
extern crate fnv;
diff --git a/components/gfx/platform/freetype/font_context.rs b/components/gfx/platform/freetype/font_context.rs
index c60c6bf5e36..b8b70c2b42e 100644
--- a/components/gfx/platform/freetype/font_context.rs
+++ b/components/gfx/platform/freetype/font_context.rs
@@ -10,35 +10,72 @@ use freetype::freetype::FT_Memory;
use freetype::freetype::FT_New_Library;
use freetype::freetype::struct_FT_MemoryRec_;
+use alloc::heap;
use std::ptr;
use std::rc::Rc;
+use util::mem::{HeapSizeOf, heap_size_of};
-use libc::{self, c_void, c_long, size_t};
+use libc::{c_void, c_long};
-extern fn ft_alloc(_mem: FT_Memory, size: c_long) -> *mut c_void {
+// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
+// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
+// record the memory usage of each FreeType instance.
+struct User {
+ size: usize,
+}
+
+// FreeType doesn't require any particular alignment for allocations.
+const FT_ALIGNMENT: usize = 0;
+
+extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
unsafe {
- let ptr = libc::malloc(size as size_t);
- ptr as *mut c_void
+ let ptr = heap::allocate(req_size as usize, FT_ALIGNMENT) as *mut c_void;
+ let actual_size = heap_size_of(ptr);
+
+ let user = (*mem).user as *mut User;
+ (*user).size += actual_size;
+
+ ptr
}
}
-extern fn ft_free(_mem: FT_Memory, block: *mut c_void) {
+extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
unsafe {
- libc::free(block);
+ let actual_size = heap_size_of(ptr);
+
+ let user = (*mem).user as *mut User;
+ (*user).size -= actual_size;
+
+ heap::deallocate(ptr as *mut u8, actual_size, FT_ALIGNMENT);
}
}
-extern fn ft_realloc(_mem: FT_Memory, _cur_size: c_long, new_size: c_long, block: *mut c_void) -> *mut c_void {
+extern fn ft_realloc(mem: FT_Memory, _cur_size: c_long, new_req_size: c_long,
+ old_ptr: *mut c_void) -> *mut c_void {
unsafe {
- let ptr = libc::realloc(block, new_size as size_t);
- ptr as *mut c_void
+ let old_actual_size = heap_size_of(old_ptr);
+ let new_ptr = heap::reallocate(old_ptr as *mut u8, old_actual_size,
+ new_req_size as usize, FT_ALIGNMENT) as *mut c_void;
+ let new_actual_size = heap_size_of(new_ptr);
+
+ let user = (*mem).user as *mut User;
+ (*user).size += new_actual_size - old_actual_size;
+
+ new_ptr
}
}
+// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
+// rustc. But using a typedef avoids this, so...
+pub type UserPtr = *mut User;
+
+// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
+// FontContextHandle.
#[derive(Clone)]
pub struct FreeTypeLibraryHandle {
pub ctx: FT_Library,
- pub mem: FT_Memory,
+ mem: FT_Memory,
+ user: UserPtr,
}
impl Drop for FreeTypeLibraryHandle {
@@ -47,19 +84,37 @@ impl Drop for FreeTypeLibraryHandle {
unsafe {
FT_Done_Library(self.ctx);
Box::from_raw(self.mem);
+ Box::from_raw(self.user);
}
}
}
-#[derive(Clone)]
+impl HeapSizeOf for FreeTypeLibraryHandle {
+ fn heap_size_of_children(&self) -> usize {
+ let ft_size = unsafe { (*self.user).size };
+ ft_size +
+ heap_size_of(self.ctx as *const c_void) +
+ heap_size_of(self.mem as *const c_void) +
+ heap_size_of(self.user as *const c_void)
+ }
+}
+
+#[derive(Clone, HeapSizeOf)]
pub struct FontContextHandle {
+ // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
+ // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
+ // once, otherwise we'll get crashes. Yuk.
pub ctx: Rc<FreeTypeLibraryHandle>,
}
impl FontContextHandle {
pub fn new() -> FontContextHandle {
+ let user = box User {
+ size: 0,
+ };
+ let user: *mut User = ::std::boxed::into_raw(user);
let mem = box struct_FT_MemoryRec_ {
- user: ptr::null_mut(),
+ user: user as *mut c_void,
alloc: ft_alloc,
free: ft_free,
realloc: ft_realloc,
@@ -74,7 +129,7 @@ impl FontContextHandle {
FT_Add_Default_Modules(ctx);
FontContextHandle {
- ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem }),
+ ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
}
}
}
diff --git a/components/gfx/platform/macos/font_context.rs b/components/gfx/platform/macos/font_context.rs
index e35aadb9910..ca718de09ca 100644
--- a/components/gfx/platform/macos/font_context.rs
+++ b/components/gfx/platform/macos/font_context.rs
@@ -2,6 +2,8 @@
* 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 util::mem::HeapSizeOf;
+
#[derive(Clone)]
pub struct FontContextHandle {
ctx: ()
@@ -13,3 +15,9 @@ impl FontContextHandle {
FontContextHandle { ctx: () }
}
}
+
+impl HeapSizeOf for FontContextHandle {
+ fn heap_size_of_children(&self) -> usize {
+ 0
+ }
+}