New issue
Advanced search Search tips

Issue 665280 link

Starred by 3 users

Issue metadata

Status: Duplicate
Merged: issue 850128
Owner:
Closed: Jun 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 3
Type: Bug

Blocked on:
issue 791391


Participants' hotlists:
MacViews-Task-Queue


Sign in to add a comment

[Mac]Views: Improve window resize performance e.g. Task Manager, gfx::Canvas::DrawStringRectWithFlags (and, e.g., RenderTextMac vs RenderTextHarfbuzz plus shared parts)

Project Member Reported by tapted@chromium.org, Nov 15 2016

Issue description

Chrome Version       : 56.0.2914.3
OS Version: OS X 10.12.1

What steps will reproduce the problem?
1. With MacViews, open the Task Manager, resize it a bunch

What is the expected result?

Smooth resize

What happens instead of that?

Even on a high performance machine, ui::WindowResizeHelperMac sometimes fails to receive a frame within 50ms and redraws the window frame without an updated window contents, resulting in black gumf around the window edge. (we put up with this on Windows and Linux, but we're fussier on Mac).

Both RenderTextMac and RenderTextHarfbuzz seem to have similar CPU usage, but I think there's some low-hanging fruit in RenderTextHarfbuzz that could put it on top. (e.g. calls to gfx::Font::Derive that could be cached)

At a glance, I think there's some low-hanging fruit in the shared parts too. E.g. there are multiple calls to EnsureLayout under DrawStringRectWithFlags -- one for drawing, one for eliding. There might be a way to layout only once and effectively double performance.

Attaching symbolized two traces: one with --enable-harfbuzz-rendertext and one without, for the "resize task manager a bunch" test case, over 3000ms.

Note there's some noise in the delay between me hitting "sample" and starting to resizing the window. Noteworthy bits:

- gfx::Canvas::DrawStringRectWithFlags: 158ms harfbuzz, 184ms mac
- DrawStringRectWithFlags calling EnsureLayout multipe times: once for elide, once for draw
- Also a layout called via gfx::Canvas::GetStringWidth
 - which is also called via views::CalculateTableColumnSizes
- A surprising (to me) sample taken inside FontListImpl::GetFonts(): It has a CHECK(FontList::ParseDescription(..)) which might be expensive in release code.
- noticable std::vector<gfx::BreakList> memory management in gfx::internal::StyleIterator::StyleIterator
- ui::FormatBytes isn't cheap (4% of drawing time)

Latency
 - base::WaitableEvent::Wait in content::BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface
 - IPC::SyncChannel::WaitForReply in gpu::GpuChannelHost::ValidateFlushIDReachedServer

The Window resize
 - ScreenMac::GetDisplayNearestWindow is slow (called by WidgetDelegate::SaveWindowPlacement, AND by BridgedNativeWidget::UpdateLayerProperties(), when under BridgedNativeWidget::OnSizeChanged()) (the slow bit is mostly under -[NSWindow _bestScreenBySpaceAssignmentOrGeometry]). Also called internally by AppKit under -[_NSViewLayerSurface update] (under [NSThemeFrame setFrameSize:], and under -[NSView _invalidateFocus] of BridgedContentView).
 - and under -[NSWindow showsFullScreenButton]!!

**  - AND called under gfx::ApplyNSWindowSizeConstraints(..) - this is triggered by views::View::BoundsChanged(..) calling views::BridgedNativeWidget::OnSizeConstraintsChanged() -- maybe that can be avoided entirely. For a 100ms saving.
  - wow - I have an easy fix for this already - https://codereview.chromium.org/2502813003/

Other stuff
 - -[AppMenuButtonViewController containerSuperviewFrameChanged:] gets a notification posted when the window resizes -- why? (probably not filtering its subscription properly).


Everything, ranked.

-[NSWindow _bestScreenBySpaceAssignmentOrGeometry]
        27       -[NSCGSWindow(NSCGSSpace) bestSpaceContainingWindow]  (in AppKit) + 39  [0x7fff81cf72f4]
        27       -[NSWindow _bestScreenByGeometryOfFrame:respectingSpaceAssignment:]  (in AppKit) + 654  [0x7fff81727934]
        27       -[NSWindow _bestScreenBySpaceAssignmentOrGeometry]  (in AppKit) + 71  [0x7fff8172769d]
        24       NSCGSWindowBestManagedDisplayMatchesByGeometry  (in AppKit) + 231  [0x7fff8189f737]
        23       -[NSCGSWindow(NSCGSSpace) bestSpaceContainingWindow]  (in AppKit) + 63  [0x7fff81cf730c]
        23       SLSCopyBestManagedDisplayForRect  (in SkyLight) + 327  [0x7fff94f2ec45]
        22       SLSCopySpacesForWindows  (in SkyLight) + 199  [0x7fff94f2bfe5]
        22       _NSCGSWindowGetSpaceIDs  (in AppKit) + 115  [0x7fff81cf72a6]
        21       NSCGSWindowBestManagedDisplayMatchesByGeometry  (in AppKit) + 261  [0x7fff8189f755]
        21       __SLSCopySpacesForWindows_block_invoke  (in SkyLight) + 175  [0x7fff94f2c0bc]
        19       SLSCopyManagedDisplayForWindow  (in SkyLight) + 170  [0x7fff94f2ed63]

-[NSWindow showsFullScreenButton]
        14       -[NSWindow _implicitlyAllowsFullScreenPrimary]  (in AppKit) + 233  [0x7fff81733242]
        7       -[NSWindow _effectiveCollectionBehavior]  (in AppKit) + 50  [0x7fff81732dbe]
        7       -[NSWindow _implicitlyAllowsFullScreenPrimary]  (in AppKit) + 322  [0x7fff8173329b]

gfx::Font::Derive
        17       -[NSFontManager traitsOfFont:]  (in AppKit) + 37  [0x7fff818b3183]
        16       -[NSCTFontDescriptor objectForKey:]  (in UIFoundation) + 21  [0x7fff961656cb]
        16       -[NSFontDescriptor symbolicTraits]  (in UIFoundation) + 33  [0x7fff96164e7a]
        16       CTFontDescriptorCopyAttribute  (in CoreText) + 98  [0x7fff8500e8bb]
        11       TDescriptor::CopyAttribute(__CFString const*) const  (in CoreText) + 204  [0x7fff8500e9c4]
        9       -[NSFontManager convertFont:toHaveTrait:]  (in AppKit) + 92  [0x7fff819ac89b]
        9       -[NSFontManager convertFont:toNotHaveTrait:]  (in AppKit) + 36  [0x7fff819ac763]
        9       gfx::Font::Derive(int, int, gfx::Font::Weight) const  (in Google Chrome Framework)  load address 0x103188000 + 0x1dcd3d1  [font.cc:45]
        9       gfx::internal::CreateSkiaTypeface(gfx::Font const&, bool, gfx::Font::Weight)  (in Google Chrome Framework)  load address 0x103188000 + 0x1dea414  [render_text_mac.mm:76]
        9       TComponentFont::CopyAttribute(unsigned long) const  (in CoreText) + 88  [0x7fff8500f890]
        9       TTenuousComponentFont::CopyAttribute(unsigned long) const  (in CoreText) + 61  [0x7fff850ec161]
        8       -[NSFontManager convertFont:toHaveTrait:]  (in AppKit) + 121  [0x7fff819ac8b8]
        7       gfx::PlatformFontMac::PlatformFontMac(NSFont*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, int, gfx::Font::Weight)  (in Google Chrome Framework)  load address 0x103188000 + 0x1dd7ba6  [platform_font_mac.mm:192]
        7       gfx::PlatformFontMac::DeriveFont(int, int, gfx::Font::Weight) const  (in Google Chrome Framework)  load address 0x103188000 + 0x1dd7cda  [platform_font_mac.mm:190]
        7       TBaseFont::CopyAttribute(unsigned long) const  (in CoreText) + 336  [0x7fff8500fa02]
        7       TDescriptor::CopyAttribute(__CFString const*) const  (in CoreText) + 30  [0x7fff8500e916]
        6       gfx::PlatformFontMac::DeriveFont(int, int, gfx::Font::Weight) const  (in Google Chrome Framework)  load address 0x103188000 + 0x1dd7c71  [platform_font_mac.mm:112]
        6       TBaseFont::CopyTraits(bool) const  (in CoreText) + 35  [0x7fff850e5c0b]
        6       TBaseFont::CopyTraitsInternal() const  (in CoreText) + 43  [0x7fff85029733]
        5       gfx::PlatformFontMac::DeriveFont(int, int, gfx::Font::Weight) const  (in Google Chrome Framework)  load address 0x103188000 + 0x1dd7c92  [platform_font_mac.mm:114]
        5       gfx::PlatformFontMac::DeriveFont(int, int, gfx::Font::Weight) const  (in Google Chrome Framework)  load address 0x103188000 + 0x1dd7cac  [platform_font_mac.mm:117]

RenderText layout (HarfBuzz)
        10       gfx::RenderTextHarfBuzz::EnsureLayoutRunList()  (in Google Chrome Framework)  load address 0x103188000 + 0x1de421e  [iterator:1311]
        10       gfx::RenderTextHarfBuzz::ShapeRunWithFont(std::__1::basic_string<unsigned short, base::string16_char_traits, std::__1::allocator<unsigned short> > const&, gfx::Font const&, gfx::FontRenderParams const&, gfx::internal::TextRunHarfBuzz*)  (in Google Chrome Framework)  load address 0x103188000 + 0x1de77c6  [SkRefCnt.h:308]
        10       gfx::RenderTextHarfBuzz::ShapeRun(std::__1::basic_string<unsigned short, base::string16_char_traits, std::__1::allocator<unsigned short> > const&, gfx::internal::TextRunHarfBuzz*)  (in Google Chrome Framework)  load address 0x103188000 + 0x1de7d64  [render_text_harfbuzz.cc:1350]
        9       gfx::RenderTextHarfBuzz::EnsureLayoutRunList()  (in Google Chrome Framework)  load address 0x103188000 + 0x1de41bd  [render_text_harfbuzz.cc:1569]


toolkit-views framework stuff [actually this is calling NSWindow schedulePaintInRect, which takes up more of the time]
        9       views::View::SchedulePaintInRect(gfx::Rect const&)  (in Google Chrome Framework)  load address 0x103188000 + 0x30f0084  [view.cc:760]


The rest are probably hard to improve on: moved into more_things_ranked.txt
 
TRIMMED_harfbuzz_draw_string_rect.txt
119 KB View Download
harfbuzz_draw_string_rect.txt
1.1 MB View Download
render_text_mac_draw_string_rect.txt
1.1 MB View Download
more_things_ranked.txt
13.3 KB View Download
Project Member

Comment 1 by bugdroid1@chromium.org, Nov 17 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/8a4c12c91010469d7f39332b5d54e61583b5ca4d

commit 8a4c12c91010469d7f39332b5d54e61583b5ca4d
Author: tapted <tapted@chromium.org>
Date: Thu Nov 17 09:04:58 2016

MacViews: Set initial window size constraints in OnWidgetInitDone rather than OnRootViewLayout.

OnWidgetInitDone() didn't exist when size constraints were implemented
for MacViews. The non-client view is added immediately *after* the call
NativeWidget*::InitNativeWidget() so, to ensure size constraints
correctly accounted for size constraints from the NonClientView, it was
necessary to update them in OnRootViewLayout(). However, this is called
a lot, and gfx::ApplyNSWindowSizeConstraints(..) is surprisingly CPU
intensive within AppKit code.

OnWidgetInitDone() is a much better place for applying size constraints
from the non-client view. It was introduced in r368141 specifically to
fix problems synchronising with the client area size.

BUG= 665280 
TEST=Covered by existing tests.

Review-Url: https://codereview.chromium.org/2502813003
Cr-Commit-Position: refs/heads/master@{#432821}

[modify] https://crrev.com/8a4c12c91010469d7f39332b5d54e61583b5ca4d/ui/views/widget/native_widget_mac.mm

Project Member

Comment 2 by bugdroid1@chromium.org, Nov 20 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/37ff93058a11ab26e575152d207b849c009a4a00

commit 37ff93058a11ab26e575152d207b849c009a4a00
Author: tapted <tapted@chromium.org>
Date: Sun Nov 20 23:47:03 2016

Remove Widget::OnRootViewLayout().

It was added early on in the development for Linux Aura (r222386) to
propagate min/max window size properties to the window server. However,
it never really worked right because mapping the x11 window is
asynchronous: there's no guarantee a layout would occur after the window
was mapped. This was fixed in r325538 (and moved around in r388040 and
r389572).

Furthermore, calls to SetBounds() will also update the min and max size
properties. This is since r283945 (and a fix for that in r350338), so
the associated OnRootViewLayout() call is redundant.

Mac was also using OnRootViewLayout() but r368141 added
OnWidgetInitDone() which is a better place to trigger this. Mac
stopped using OnRootViewLayout() in r432821.

BUG= 665280 
TEST=Should be covered by WidgetTest.MinimumSizeConstraints added in
r325538

Review-Url: https://codereview.chromium.org/2507403002
Cr-Commit-Position: refs/heads/master@{#433462}

[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/mus/desktop_window_tree_host_mus.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/mus/desktop_window_tree_host_mus.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/mus/native_widget_mus.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/mus/native_widget_mus.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_window_tree_host.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/native_widget_aura.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/native_widget_aura.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/native_widget_mac.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/native_widget_mac.mm
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/native_widget_private.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/root_view.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/root_view.h
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/widget.cc
[modify] https://crrev.com/37ff93058a11ab26e575152d207b849c009a4a00/ui/views/widget/widget.h

Project Member

Comment 3 by bugdroid1@chromium.org, Nov 20 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/7330ed4e42141778cb25604dd4949471f034a38f

commit 7330ed4e42141778cb25604dd4949471f034a38f
Author: tapted <tapted@chromium.org>
Date: Sun Nov 20 23:48:55 2016

Mac: Use a cache for ScreenMac::GetDisplayForScreen().

Performance traces on the associated bugs turn up a lot of time spent in
display::screen_mac::GetDisplayForScreen(). It does a lot of work, and
calls some expensive AppKit and CoreGraphics methods. It's currently
invoked multiple times during a window resize.

GetDisplayNearestWindow would also invoke -[NSWindow
_bestScreenBySpaceAssignmentOrGeometry] which does some synchronous
messaging with the window server process, adding significant latency.

ScreenMac already maintains a std::vector<Display>, but
GetDisplayForScreen() does not use it.

Use it.

Optimize GetDisplayNearestWindow for the case of a single display.

BUG= 666556 ,  665280 

Review-Url: https://codereview.chromium.org/2514703002
Cr-Commit-Position: refs/heads/master@{#433463}

[modify] https://crrev.com/7330ed4e42141778cb25604dd4949471f034a38f/ui/display/mac/screen_mac.mm

Cc: -tapted@chromium.org ellyjo...@chromium.org
Labels: -Pri-3 MacViews-Dialogs Pri-2
Owner: tapted@chromium.org
tapted: how is this looking now?

Comment 5 by tapted@chromium.org, Apr 13 2017

Labels: -Pri-2 Pri-3
Performance is good, but there's more to do. I want to get rid of calls to Font::Derive in RenderText (the fonts are usually already cached in ResourceBundle already and Derive is slow).

Caching text runs is also a possibility. See http://crbug.com/641726#c27 and http://crbug.com/641726#c29

For Mac to get these benefits, we should deploy harfbuzz more widely there first ( Issue 454835 ). That has its own set of problems.
Labels: -Performance Performance-Responsiveness
Labels: MacViews-Browser M-X
This bug affects resizeable MacViews windows, of which there's only one that I know of (the bookmark editor). Also, I don't see any noticeable problems with that window. I'm going to say we can defer fixing this until after launch if we need to, so M-X and MacViews-Browser.
Blockedon: 791391
Cc: tapted@chromium.org
Labels: -M-X Target-69
Owner: sdy@chromium.org
MacViews triage: assigning this to sdy@ because they own related work; let's target a fix for this (if there is further work we want to do) at M-69.
Maybe related to  issue 682825 , too.
Components: UI>TaskManager
The switch from RenderTextMac to RenderTextHarfbuzz for views (Issue 791391) may have had an impact on this too.

There's also Issue 740717, which I just remembered is assigned to me.. Basically a big refactor of TableView to cache RenderText objects. I think this will fix the lion's share of remaining performance concerns here.
Labels: M-69
Mergedinto: 850128
Status: Duplicate (was: Assigned)
Triage: 850128 will track this work.
Labels: -M-69 Group-Performance

Sign in to add a comment