Millions of heap allocations to fill rectangles and glyphs when viewing Treeherder

RESOLVED WORKSFORME

Status

()

RESOLVED WORKSFORME
4 years ago
4 years ago

People

(Reporter: njn, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

4 years ago
I have some more Treeherder heap allocation measurements from DMD.

First, we create a *lot* of Cairo patterns in order to fill rectangles and
glyphs:

> Cumulative {
>   1,075,692 blocks in heap block record 2 of 15,540
>   172,110,720 bytes (163,505,184 requested / 8,605,536 slop)
>   Individual block sizes: 160 x 1,075,692
>   4.48% of the heap (11.71% cumulative)
>   Allocated at {
>     #01: _cairo_pattern_create_solid (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-pattern.c:489)
>     #02: INT__moz_cairo_pattern_create_rgba (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-pattern.c:593)
>     #03: mozilla::gfx::GfxPatternToCairoPattern(mozilla::gfx::Pattern const&, float) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:469)
>     #04: mozilla::gfx::DrawTargetCairo::DrawPattern(mozilla::gfx::Pattern const&, mozilla::gfx::StrokeOptions const&, mozilla::gfx::DrawOptions const&, mozilla::gfx::DrawTargetCairo::DrawPatternType, bool) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:866)
>     #05: mozilla::gfx::DrawTargetCairo::FillRect(mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:961)
>   }
> }
> 
> Cumulative {
>   161,180 blocks in heap block record 12 of 15,540
>   25,788,800 bytes (24,499,360 requested / 1,289,440 slop)
>   Individual block sizes: 160 x 161,180
>   0.67% of the heap (44.14% cumulative)
>   Allocated at {
>     #01: _cairo_pattern_create_solid (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-pattern.c:489)
>     #02: INT__moz_cairo_pattern_create_rgba (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-pattern.c:593)
>     #03: mozilla::gfx::GfxPatternToCairoPattern(mozilla::gfx::Pattern const&, float) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:469)
>     #04: mozilla::gfx::DrawTargetCairo::FillGlyphs(mozilla::gfx::ScaledFont*, mozilla::gfx::GlyphBuffer const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&, mozilla::gfx::GlyphRenderingOptions const*) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:1143)
>     #05: GlyphBufferAzure::Flush(bool) (/home/njn/moz/mi4/o64dmd/gfx/thebes/../../../gfx/thebes/gfxFont.cpp:1611)
>   }
> }

And then, for the rectangles (which dominate), we create a clip path as well:

> Cumulative {
>   625,379 blocks in heap block record 3 of 28,149
>   640,388,096 bytes (395,239,528 requested / 245,148,568 slop)
>   Individual block sizes: 1,024 x 625,379
>   16.66% of the heap (23.82% cumulative)
>   Allocated at {
>     #01: _cairo_clip_path_create (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-clip.c:62)
>     #02: _cairo_clip_intersect_rectangle (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-clip.c:143)
>     #03: _cairo_clip_to_boxes (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-clip.c:1446)
>     #04: _cairo_surface_fallback_fill (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-surface-fallback.c:1156)
>     #05: _cairo_surface_fill (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-surface.c:2363)
>     #06: _cairo_gstate_fill (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo-gstate.c:1290)
>     #07: INT__moz_cairo_fill_preserve (/home/njn/moz/mi4/o64dmd/gfx/cairo/cairo/src/../../../../../gfx/cairo/cairo/src/cairo.c:2464)
>     #08: mozilla::gfx::DrawTargetCairo::DrawPattern(mozilla::gfx::Pattern const&, mozilla::gfx::StrokeOptions const&, mozilla::gfx::DrawOptions const&, mozilla::gfx::DrawTargetCairo::DrawPatternType, bool) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:910)
>     #09: mozilla::gfx::DrawTargetCairo::FillRect(mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&) (/home/njn/moz/mi4/o64dmd/gfx/2d/../../../gfx/2d/DrawTargetCairo.cpp:961)
>     #10: DrawSolidBorderSegment(nsRenderingContext&, nsRect, unsigned int, int, int, unsigned char, int, unsigned char, int) (/home/njn/moz/mi4/o64dmd/layout/base/../../../layout/base/nsCSSRendering.cpp:3727)
>   }
> }

In total, these account for over 10% of all heap allocations in the child
process (this is allocation *counts*, not *size*).

This feels rather heavyweight for filling in rectangles. But I don't know this
code at all; maybe it's unavoidable.
(Reporter)

Comment 1

4 years ago
One thing to note: _cairo_pattern_create_solid() has a pattern pool which allows patterns to be reused. But we configure Cairo such that it's not used. This may be a perfectly reasonable thing to do; I'm just pointing it out because it's potentially confusing.
(Reporter)

Comment 2

4 years ago
Created attachment 8536907 [details]
The data from comment 0, but with longer stack traces

The attached file shows the data from comment 0, but with longer stack traces, in case that's helpful.
(In reply to Nicholas Nethercote [:njn] from comment #1)
> One thing to note: _cairo_pattern_create_solid() has a pattern pool which
> allows patterns to be reused. But we configure Cairo such that it's not
> used. This may be a perfectly reasonable thing to do; I'm just pointing it
> out because it's potentially confusing.

I believe not using the pattern pool is a mistake. Just using that is probably the right way to fix this.
(Reporter)

Comment 4

4 years ago
> I believe not using the pattern pool is a mistake. Just using that is
> probably the right way to fix this.

The pattern pool is enabled if HAS_ATOMIC_OPS is true. It is set to true if any of HAVE_INTEL_ATOMIC_PRIMITIVES, HAVE_LIB_ATOMIC_OPS, HAVE_OS_ATOMIC_OPS are true. I don't know what dictates if they are true; each of those identifiers appear exactly once in the codebase, so they must have to be defined from outside, and I don't recognize the atomic primitives used within the three cases. So I don't know how to enable this.
(Reporter)

Updated

4 years ago
Depends on: 1094552
Depends on: 1112121
(In reply to Nicholas Nethercote [:njn] from comment #4)
> > I believe not using the pattern pool is a mistake. Just using that is
> > probably the right way to fix this.
> 
> The pattern pool is enabled if HAS_ATOMIC_OPS is true. It is set to true if
> any of HAVE_INTEL_ATOMIC_PRIMITIVES,

See https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/_005f_005fsync-Builtins.html#_005f_005fsync-Builtins

> HAVE_LIB_ATOMIC_OPS,

See https://github.com/ivmai/libatomic_ops/

> HAVE_OS_ATOMIC_OPS

See https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/OSAtomicAdd32.3.html
Blocks: 1112352

Comment 6

4 years ago
Nicholas, thank you for filing this and the others! :-)

Updated

4 years ago
Depends on: 967300
No longer depends on: 1112121
(Reporter)

Comment 7

4 years ago
I just checked with DMD -- with bug 967300 having been fixed all the calls _cairo_pattern_create_solid() on Linux are gone. When I measured earlier on Windows there weren't many calls to that function.

And on Linux almost all of the calls to _cairo_clip_path_create() have gone as well. Not sure why. But I think we can declare victory here.
Status: NEW → RESOLVED
Last Resolved: 4 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.