06a785bf1e
When clicking the "toplist by retained memory" button in Observatory
it always asks to find 10 objects of a specific size.
The previous implementation did this by taking all objects (millions if
using a lot of memory), sorting it (O(n log n)), filtering it (O(n)),
and ".take"ing the 10 we wanted. Total runtime should be O(n log n)
where n is the number of objects in the heap.
This CL optimizes this for the (to my knowledge) only case there exists,
and instead, while iterationg over all elements (O(n)) keeps a sorted
working list of the top m objects (this is 10 for all intents and purpose
as far as I can see; I've if-cased it to be at most 20). Total runtime
should be O(n log m) where n is the number of objects in the heap and m
is the requested number, which - as said - is at most 20, i.e. a constant,
maying that the runtime is more like O(n).
Instrumenting the code slightly to measure how long it takes:
```
diff --git a/runtime/observatory/lib/src/repositories/top_retaining_instances.dart b/runtime/observatory/lib/src/repositories/top_retaining_instances.dart
index 400ac1427ed..b7e5c429fac 100644
--- a/runtime/observatory/lib/src/repositories/top_retaining_instances.dart
+++ b/runtime/observatory/lib/src/repositories/top_retaining_instances.dart
@@ -7,6 +7,8 @@ part of repositories;
class TopRetainingInstancesRepository
implements M.TopRetainingInstancesRepository {
Future<Iterable<M.RetainingObject>> get(M.IsolateRef i, M.ClassRef c) async {
+ Stopwatch stopwatch = new Stopwatch()..start();
+ try {
S.Isolate isolate = i as S.Isolate;
S.Class cls = c as S.Class;
assert(isolate != null);
@@ -18,5 +20,9 @@ class TopRetainingInstancesRepository
return (await Future.wait(
snapshot.getMostRetained(isolate, classId: cls.vmCid, limit: 10)))
.map((object) => new S.RetainingObject(object));
+ } finally {
+ int ms = stopwatch.elapsedMilliseconds;
+ print("TopRetainingInstancesRepository took $ms ms.");
+ }
}
}
```
I ran this program:
```
import "dart:isolate";
List<Object> data = [];
main() {
RawReceivePort preventClose = new RawReceivePort();
for(int i = 0; i < 10000000; i++) {
data.add(new List<int>()..add(i));
}
for(int i = 0; i < 100000; i++) {
data.add(new Foo(i));
}
}
class Foo {
final int i;
Foo(this.i);
}
```
and requested the toplist by retained memory for class `Foo`.
What before took 121778 ms now takes 81026 ms.
(For smaller numbers in the same test it went from ~10 seconds to ~8 seconds).
Change-Id: I6aee4b0c91af8a9ade116b79e56d1e6cbbee5d09
Reviewed-on: https://dart-review.googlesource.com/70502
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>