mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 08:31:29 +00:00
[analyzer] Report memory usage on Windows too
Change-Id: I6a31370c51e40a9593f8875d365a43d9f4111aaf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275660 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Jens Johansen <jensj@google.com>
This commit is contained in:
parent
c6d287cc05
commit
959f0a299c
|
@ -1065,8 +1065,10 @@ class MemoryAndCpuPage extends DiagnosticPageWithNav {
|
|||
var serviceProtocolInfo = await developer.Service.getInfo();
|
||||
|
||||
if (usage != null) {
|
||||
buf.writeln(
|
||||
writeOption('CPU', printPercentage(usage.cpuPercentage / 100.0)));
|
||||
var cpuPercentage = usage.cpuPercentage;
|
||||
if (cpuPercentage != null) {
|
||||
buf.writeln(writeOption('CPU', printPercentage(cpuPercentage / 100.0)));
|
||||
}
|
||||
buf.writeln(writeOption('Memory', '${usage.memoryMB.round()} MB'));
|
||||
|
||||
h3('VM');
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
/// A class that can return memory and cpu usage information for a given
|
||||
|
@ -19,6 +20,10 @@ abstract class ProcessProfiler {
|
|||
return _PosixProcessProfiler();
|
||||
}
|
||||
|
||||
if (Platform.isWindows) {
|
||||
return _WindowsProcessProfiler();
|
||||
}
|
||||
|
||||
// Not a supported platform.
|
||||
return null;
|
||||
}
|
||||
|
@ -27,7 +32,7 @@ abstract class ProcessProfiler {
|
|||
class UsageInfo {
|
||||
/// A number between 0.0 and 100.0 * the number of host CPUs (but typically
|
||||
/// never more than slightly above 100.0).
|
||||
final double cpuPercentage;
|
||||
final double? cpuPercentage;
|
||||
|
||||
/// The process memory usage in kilobytes.
|
||||
final int memoryKB;
|
||||
|
@ -37,7 +42,12 @@ class UsageInfo {
|
|||
double get memoryMB => memoryKB / 1024;
|
||||
|
||||
@override
|
||||
String toString() => '$cpuPercentage% ${memoryMB.toStringAsFixed(1)}MB';
|
||||
String toString() {
|
||||
if (cpuPercentage != null) {
|
||||
return '$cpuPercentage% ${memoryMB.toStringAsFixed(1)}MB';
|
||||
}
|
||||
return '${memoryMB.toStringAsFixed(1)}MB';
|
||||
}
|
||||
}
|
||||
|
||||
class _PosixProcessProfiler extends ProcessProfiler {
|
||||
|
@ -74,3 +84,44 @@ class _PosixProcessProfiler extends ProcessProfiler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _WindowsProcessProfiler extends ProcessProfiler {
|
||||
_WindowsProcessProfiler() : super._();
|
||||
|
||||
@override
|
||||
Future<UsageInfo?> getProcessUsage(int processId) async {
|
||||
try {
|
||||
var result = await Process.run(
|
||||
'tasklist', ['/FI', 'PID eq $processId', '/NH', '/FO', 'csv']);
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
return Future.value(_parse(result.stdout as String));
|
||||
} catch (e) {
|
||||
return Future.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
UsageInfo? _parse(String tasklistResults) {
|
||||
try {
|
||||
var lines = tasklistResults.split(RegExp("\r?\n"));
|
||||
for (var line in lines) {
|
||||
if (line.trim().isEmpty) continue;
|
||||
// Hacky parsing of csv line.
|
||||
var entries = jsonDecode("[$line]") as List;
|
||||
if (entries.length != 5) continue;
|
||||
// E.g. 123,456 K
|
||||
var memory = entries[4] as String;
|
||||
memory = memory.substring(0, memory.indexOf(" "));
|
||||
memory = memory.replaceAll(",", "");
|
||||
memory = memory.replaceAll(".", "");
|
||||
return UsageInfo(null, int.parse(memory));
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,13 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:analysis_server/src/utilities/profiling.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('ProcessProfiler', () {
|
||||
// Skip on windows.
|
||||
if (Platform.isWindows) {
|
||||
return;
|
||||
}
|
||||
|
||||
test('getProfilerForPlatform', () async {
|
||||
expect(ProcessProfiler.getProfilerForPlatform(), isNotNull);
|
||||
});
|
||||
|
@ -22,8 +18,28 @@ void main() {
|
|||
var profiler = ProcessProfiler.getProfilerForPlatform()!;
|
||||
var info = (await profiler.getProcessUsage(pid))!;
|
||||
|
||||
expect(info.cpuPercentage, greaterThanOrEqualTo(0.0));
|
||||
print("Uses ${info.memoryKB} KB");
|
||||
|
||||
if (Platform.isWindows) {
|
||||
expect(info.cpuPercentage, isNull);
|
||||
} else {
|
||||
expect(info.cpuPercentage, greaterThanOrEqualTo(0.0));
|
||||
}
|
||||
expect(info.memoryKB, greaterThanOrEqualTo(0));
|
||||
|
||||
// Use ~50 MB more memory and ensure that we actually use more memory
|
||||
// as reported by the return value.
|
||||
Uint8List use50mb = Uint8List(50 * 1024 * 1024);
|
||||
for (int i = 0; i < use50mb.length; i++) {
|
||||
use50mb[i] = i % 200;
|
||||
}
|
||||
var info2 = (await profiler.getProcessUsage(pid))!;
|
||||
print("Now uses ${info2.memoryKB} KB");
|
||||
|
||||
for (var b in use50mb) {
|
||||
if (b < 0) throw "This shouldn't happen, but we're using the data!";
|
||||
}
|
||||
expect(info2.memoryKB, greaterThan(info.memoryKB));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue