mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add Instrumentation class (#22650)
This commit is contained in:
parent
26c4ba074d
commit
b249d568cf
@ -1801,6 +1801,11 @@ class ProductionCollector implements Collector {
|
||||
|
||||
@override
|
||||
void register(Object wrapper, SkDeletable deletable) {
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${deletable.constructor.name} registered',
|
||||
);
|
||||
}
|
||||
_skObjectFinalizationRegistry.register(wrapper, deletable);
|
||||
}
|
||||
|
||||
@ -1859,6 +1864,11 @@ class ProductionCollector implements Collector {
|
||||
// again if the objects is worth collecting.
|
||||
continue;
|
||||
}
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${deletable.constructor.name} deleted',
|
||||
);
|
||||
}
|
||||
try {
|
||||
deletable.delete();
|
||||
} catch (error, stackTrace) {
|
||||
@ -1907,6 +1917,21 @@ class SkDeletable {
|
||||
|
||||
/// Returns whether the correcponding C++ object has been deleted.
|
||||
external bool isDeleted();
|
||||
|
||||
/// Returns the JavaScript constructor for this object.
|
||||
///
|
||||
/// This is useful for debugging.
|
||||
external JsConstructor get constructor;
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class JsConstructor {
|
||||
/// The name of the "constructor", typically the function name called with
|
||||
/// the `new` keyword, or the ES6 class name.
|
||||
///
|
||||
/// This is useful for debugging.
|
||||
external String get name;
|
||||
}
|
||||
|
||||
/// Attaches a weakly referenced object to another object and calls a finalizer
|
||||
|
||||
@ -147,6 +147,11 @@ abstract class ManagedSkiaObject<T extends Object> extends SkiaObject<T> {
|
||||
} else {
|
||||
// If FinalizationRegistry is _not_ supported we may need to delete
|
||||
// and resurrect the object multiple times before deleting it forever.
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${(defaultObject as SkDeletable).constructor.name} created',
|
||||
);
|
||||
}
|
||||
if (isResurrectionExpensive) {
|
||||
SkiaObjects.manageExpensive(this);
|
||||
} else {
|
||||
@ -161,6 +166,11 @@ abstract class ManagedSkiaObject<T extends Object> extends SkiaObject<T> {
|
||||
T _doResurrect() {
|
||||
assert(!browserSupportsFinalizationRegistry);
|
||||
final T skiaObject = resurrect();
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${(skiaObject as SkDeletable).constructor.name} resurrected',
|
||||
);
|
||||
}
|
||||
rawSkiaObject = skiaObject;
|
||||
if (isResurrectionExpensive) {
|
||||
SkiaObjects.manageExpensive(this);
|
||||
@ -173,6 +183,11 @@ abstract class ManagedSkiaObject<T extends Object> extends SkiaObject<T> {
|
||||
@override
|
||||
void didDelete() {
|
||||
assert(!browserSupportsFinalizationRegistry);
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${(rawSkiaObject as SkDeletable).constructor.name} deleted',
|
||||
);
|
||||
}
|
||||
rawSkiaObject = null;
|
||||
}
|
||||
|
||||
@ -303,6 +318,11 @@ class SkiaObjectBox<R extends StackTraceDebugger, T extends Object> extends Skia
|
||||
|
||||
void _initialize(R debugReferrer, T initialValue) {
|
||||
_update(initialValue);
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${_skDeletable?.constructor.name} created',
|
||||
);
|
||||
}
|
||||
if (assertionsEnabled) {
|
||||
debugReferrers.add(debugReferrer);
|
||||
}
|
||||
@ -355,6 +375,11 @@ class SkiaObjectBox<R extends StackTraceDebugger, T extends Object> extends Skia
|
||||
assert(_resurrector != null);
|
||||
assert(!_isDeletedPermanently, 'Cannot use deleted object.');
|
||||
_update(_resurrector!());
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${_skDeletable?.constructor.name} resurrected',
|
||||
);
|
||||
}
|
||||
SkiaObjects.manageExpensive(this);
|
||||
return skiaObject;
|
||||
}
|
||||
@ -366,6 +391,11 @@ class SkiaObjectBox<R extends StackTraceDebugger, T extends Object> extends Skia
|
||||
|
||||
@override
|
||||
void didDelete() {
|
||||
if (Instrumentation.enabled) {
|
||||
Instrumentation.instance.incrementCounter(
|
||||
'${_skDeletable?.constructor.name} deleted',
|
||||
);
|
||||
}
|
||||
assert(!browserSupportsFinalizationRegistry);
|
||||
_update(null);
|
||||
}
|
||||
@ -419,7 +449,8 @@ class SkiaObjectBox<R extends StackTraceDebugger, T extends Object> extends Skia
|
||||
if (browserSupportsFinalizationRegistry) {
|
||||
Collector.instance.collect(_skDeletable!);
|
||||
} else {
|
||||
_skDeletable!.delete();
|
||||
delete();
|
||||
didDelete();
|
||||
}
|
||||
}
|
||||
rawSkiaObject = null;
|
||||
|
||||
@ -218,3 +218,66 @@ void _frameTimingsOnRasterFinish() {
|
||||
int _nowMicros() {
|
||||
return (html.window.performance.now() * 1000).toInt();
|
||||
}
|
||||
|
||||
/// Counts various events that take place while the app is running.
|
||||
///
|
||||
/// This class will slow down the app, and therefore should be disabled while
|
||||
/// benchmarking. For example, avoid using it in conjunction with [Profiler].
|
||||
class Instrumentation {
|
||||
Instrumentation._() {
|
||||
_checkInstrumentationEnabled();
|
||||
}
|
||||
|
||||
/// Whether instrumentation is enabled.
|
||||
///
|
||||
/// Check this value before calling any other methods in this class.
|
||||
static const bool enabled = const bool.fromEnvironment(
|
||||
'FLUTTER_WEB_ENABLE_INSTRUMENTATION',
|
||||
defaultValue: false,
|
||||
);
|
||||
|
||||
/// Returns the singleton that provides instrumentation API.
|
||||
static Instrumentation get instance {
|
||||
_checkInstrumentationEnabled();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
static late final Instrumentation _instance = Instrumentation._();
|
||||
|
||||
static void _checkInstrumentationEnabled() {
|
||||
if (!enabled) {
|
||||
throw Exception(
|
||||
'Cannot use Instrumentation unless it is enabled. '
|
||||
'You can enable it by setting the `FLUTTER_WEB_ENABLE_INSTRUMENTATION` '
|
||||
'environment variable to true, or by passing '
|
||||
'--dart-define=FLUTTER_WEB_ENABLE_INSTRUMENTATION=true to the flutter '
|
||||
'tool.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final Map<String, int> _counters = <String, int>{};
|
||||
Timer? _printTimer;
|
||||
|
||||
/// Increments the count of a particular event by one.
|
||||
void incrementCounter(String event) {
|
||||
_checkInstrumentationEnabled();
|
||||
final int currentCount = _counters[event] ?? 0;
|
||||
_counters[event] = currentCount + 1;
|
||||
_printTimer ??= Timer(
|
||||
const Duration(seconds: 2),
|
||||
() {
|
||||
final StringBuffer message = StringBuffer('Engine counters:\n');
|
||||
final List<MapEntry<String, int>> entries = _counters.entries.toList()
|
||||
..sort((MapEntry<String, int> a, MapEntry<String, int> b) {
|
||||
return a.key.compareTo(b.key);
|
||||
});
|
||||
for (MapEntry<String, int> entry in entries) {
|
||||
message.writeln(' ${entry.key}: ${entry.value}');
|
||||
}
|
||||
print(message);
|
||||
_printTimer = null;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,6 +292,9 @@ class TestSkDeletable implements SkDeletable {
|
||||
_isDeleted = true;
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
@override
|
||||
JsConstructor get constructor => TestJsConstructor('TestSkDeletable');
|
||||
}
|
||||
|
||||
class TestOneShotSkiaObject extends OneShotSkiaObject<SkPaint> implements SkDeletable {
|
||||
@ -310,6 +313,16 @@ class TestOneShotSkiaObject extends OneShotSkiaObject<SkPaint> implements SkDele
|
||||
rawSkiaObject?.delete();
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
@override
|
||||
JsConstructor get constructor => TestJsConstructor('TestOneShotSkiaObject');
|
||||
}
|
||||
|
||||
class TestJsConstructor implements JsConstructor{
|
||||
TestJsConstructor(this.name);
|
||||
|
||||
@override
|
||||
final String name;
|
||||
}
|
||||
|
||||
class TestSkiaObject extends ManagedSkiaObject<SkPaint> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user