Skip to content

Commit

Permalink
Optimize ContentLayers._isSubtreeDirty to reduce significant overhead…
Browse files Browse the repository at this point in the history
… caused by logs (#1964)
  • Loading branch information
knopp authored and matthew-carroll committed Apr 30, 2024
1 parent bec5b07 commit 68dada6
Showing 1 changed file with 29 additions and 11 deletions.
40 changes: 29 additions & 11 deletions super_editor/lib/src/infrastructure/content_layers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:logging/logging.dart';
import 'package:super_editor/src/infrastructure/_logging.dart';

/// Widget that displays [content] above a number of [underlays], and beneath a number of
Expand Down Expand Up @@ -208,31 +209,48 @@ class ContentLayersElement extends RenderObjectElement {

contentLayersLog.finer("Checking underlays");
for (final underlay in _underlays) {
contentLayersLog.finer(" - Is underlay ($underlay) subtree dirty? ${_isSubtreeDirty(underlay)}");
contentLayersLog.finer(() => " - Is underlay ($underlay) subtree dirty? ${_isSubtreeDirty(underlay)}");
hasDirtyElements = hasDirtyElements || _isSubtreeDirty(underlay);
}

contentLayersLog.finer("Checking overlays");
for (final overlay in _overlays) {
contentLayersLog.finer(" - Is overlay ($overlay) subtree dirty? ${_isSubtreeDirty(overlay)}");
contentLayersLog.finer(() => " - Is overlay ($overlay) subtree dirty? ${_isSubtreeDirty(overlay)}");
hasDirtyElements = hasDirtyElements || _isSubtreeDirty(overlay);
}

return hasDirtyElements;
}

static bool _isDirty = false;

bool _isSubtreeDirty(Element element) {
contentLayersLog.finest("Finding dirty children for: $element");
if (element.dirty) {
contentLayersLog.finest("Found a dirty child: $element");
_isDirty = false;
element.visitChildren(_isSubtreeDirtyVisitor);
return _isDirty;
}

// This is intentionally static to prevent closure allocation during
// the traversal of the element tree.
static void _isSubtreeDirtyVisitor(Element element) {
// Can't use the () => message syntax because it allocates a closure.
assert(() {
if (contentLayersLog.isLoggable(Level.FINEST)) {
contentLayersLog.finest("Finding dirty children for: $element");
}
return true;
}());
if (element.dirty) {
assert(() {
if (contentLayersLog.isLoggable(Level.FINEST)) {
contentLayersLog.finest("Found a dirty child: $element");
}
return true;
}());
_isDirty = true;
return;
}

bool isDirty = false;
element.visitChildren((childElement) {
isDirty = isDirty || _isSubtreeDirty(childElement);
});
return isDirty;
element.visitChildren(_isSubtreeDirtyVisitor);
}

void _onContentBuildScheduled() {
Expand Down

0 comments on commit 68dada6

Please sign in to comment.