Commit 5d15bb51 authored by Adam Barth's avatar Adam Barth

Move build() off microtasks

Rather than using a microtask to schedule component build functions, instead
use the scheduler. We now tread building just like layout and painting as a
visual update.
parent 0d7156fc
...@@ -47,7 +47,7 @@ class SkyBinding { ...@@ -47,7 +47,7 @@ class SkyBinding {
_renderView = renderViewOverride; _renderView = renderViewOverride;
} }
assert(_renderView != null); assert(_renderView != null);
scheduler.addPersistentFrameCallback(_beginFrame); scheduler.addPersistentFrameCallback(beginFrame);
assert(_instance == this); assert(_instance == this);
} }
...@@ -69,7 +69,7 @@ class SkyBinding { ...@@ -69,7 +69,7 @@ class SkyBinding {
void set root(RenderBox value) { void set root(RenderBox value) {
_renderView.child = value; _renderView.child = value;
} }
void _beginFrame(double timeStamp) { void beginFrame(double timeStamp) {
RenderObject.flushLayout(); RenderObject.flushLayout();
RenderObject.flushPaint(); RenderObject.flushPaint();
_renderView.paintFrame(); _renderView.paintFrame();
......
...@@ -7,6 +7,7 @@ import 'dart:collection'; ...@@ -7,6 +7,7 @@ import 'dart:collection';
import 'dart:sky' as sky; import 'dart:sky' as sky;
import 'package:sky/base/hit_test.dart'; import 'package:sky/base/hit_test.dart';
import 'package:sky/base/scheduler.dart' as scheduler;
import 'package:sky/mojo/activity.dart' as activity; import 'package:sky/mojo/activity.dart' as activity;
import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/object.dart';
...@@ -651,6 +652,11 @@ abstract class Component extends Widget { ...@@ -651,6 +652,11 @@ abstract class Component extends Widget {
_scheduleComponentForRender(this); _scheduleComponentForRender(this);
} }
static void flushBuild() {
if (!_dirtyComponents.isEmpty)
_buildDirtyComponents();
}
Widget build(); Widget build();
} }
...@@ -759,13 +765,15 @@ void _absorbDirtyComponents(List<Component> list) { ...@@ -759,13 +765,15 @@ void _absorbDirtyComponents(List<Component> list) {
} }
void _buildDirtyComponents() { void _buildDirtyComponents() {
assert(!_dirtyComponents.isEmpty);
Stopwatch sw; Stopwatch sw;
if (_shouldLogRenderDuration) if (_shouldLogRenderDuration)
sw = new Stopwatch()..start(); sw = new Stopwatch()..start();
_inRenderDirtyComponents = true; _inRenderDirtyComponents = true;
try { try {
sky.tracing.begin('Widgets._buildDirtyComponents'); sky.tracing.begin('Component.flushBuild');
List<Component> sortedDirtyComponents = new List<Component>(); List<Component> sortedDirtyComponents = new List<Component>();
_absorbDirtyComponents(sortedDirtyComponents); _absorbDirtyComponents(sortedDirtyComponents);
int index = 0; int index = 0;
...@@ -784,7 +792,7 @@ void _buildDirtyComponents() { ...@@ -784,7 +792,7 @@ void _buildDirtyComponents() {
} finally { } finally {
_buildScheduled = false; _buildScheduled = false;
_inRenderDirtyComponents = false; _inRenderDirtyComponents = false;
sky.tracing.end('Widgets._buildDirtyComponents'); sky.tracing.end('Component.flushBuild');
} }
Widget._notifyMountStatusChanged(); Widget._notifyMountStatusChanged();
...@@ -795,21 +803,20 @@ void _buildDirtyComponents() { ...@@ -795,21 +803,20 @@ void _buildDirtyComponents() {
if (_debugFrameTimes.length >= 1000) { if (_debugFrameTimes.length >= 1000) {
_debugFrameTimes.sort(); _debugFrameTimes.sort();
const int i = 99; const int i = 99;
print('_buildDirtyComponents: ${i+1}th fastest frame out of the last ${_debugFrameTimes.length}: ${_debugFrameTimes[i]} microseconds'); print('Component.flushBuild: ${i+1}th fastest frame out of the last ${_debugFrameTimes.length}: ${_debugFrameTimes[i]} microseconds');
_debugFrameTimes.clear(); _debugFrameTimes.clear();
} }
} }
} }
void _scheduleComponentForRender(Component c) { void _scheduleComponentForRender(Component component) {
_dirtyComponents.add(c); _dirtyComponents.add(component);
if (!_buildScheduled) { if (!_buildScheduled) {
_buildScheduled = true; _buildScheduled = true;
new Future.microtask(_buildDirtyComponents); scheduler.ensureVisualUpdate();
} }
} }
// RenderObjectWrappers correspond to a desired state of a RenderObject. // RenderObjectWrappers correspond to a desired state of a RenderObject.
// They are fully immutable, with one exception: A Widget which is a // They are fully immutable, with one exception: A Widget which is a
// Component which lives within an MultiChildRenderObjectWrapper's // Component which lives within an MultiChildRenderObjectWrapper's
...@@ -1178,6 +1185,11 @@ class WidgetSkyBinding extends SkyBinding { ...@@ -1178,6 +1185,11 @@ class WidgetSkyBinding extends SkyBinding {
} }
} }
void beginFrame(double timeStamp) {
Component.flushBuild();
super.beginFrame(timeStamp);
}
} }
abstract class App extends StatefulComponent { abstract class App extends StatefulComponent {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment