Skip to content

Commit b55b2bb

Browse files
bwilkersonCommit Queue
authored andcommitted
Refactor the performance reporting support
This CL contains no functional differences; it just reorganizes the code. I expect to be adding data to the collected report, and I decided that it would be better to break the massive method up before doing so in order to improve overall readability. I also wondered whether we might want to structure the data in a similar way. For example, the top-level map could have entries corresponding to each of these methods, each of which has a value that is a map containing the data collected by that method. I don't know whether this would make the output easier to read or whether the current form is depended on anywhere, but it's something to consider for the future. Change-Id: Id0ef3c2f64b00ea58069c496e7c485c7b3f163c9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430560 Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]>
1 parent 10dd59c commit b55b2bb

File tree

1 file changed

+156
-111
lines changed

1 file changed

+156
-111
lines changed

pkg/analysis_server/lib/src/status/diagnostics.dart

Lines changed: 156 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -552,41 +552,39 @@ class CollectReportPage extends DiagnosticPage {
552552
return await super.generatePage(params);
553553
}
554554

555+
/// Returns a json encoding of a map containing the data to be collected.
555556
Future<String> _collectAllData() async {
556557
Map<String, Object?> collectedData = {};
557558
var server = this.server;
558559

559-
// General data.
560-
collectedData['currentTime'] = DateTime.now().millisecondsSinceEpoch;
561-
collectedData['operatingSystem'] = Platform.operatingSystem;
562-
collectedData['version'] = Platform.version;
563-
collectedData['clientId'] = server.options.clientId;
564-
collectedData['clientVersion'] = server.options.clientVersion;
565-
collectedData['protocolVersion'] = PROTOCOL_VERSION;
566-
collectedData['serverType'] = server.runtimeType.toString();
567-
collectedData['uptime'] = server.uptime.toString();
568-
if (server is LegacyAnalysisServer) {
569-
collectedData['serverServices'] =
570-
server.serverServices.map((e) => e.toString()).toList();
571-
} else if (server is LspAnalysisServer) {
572-
collectedData['clientDiagnosticInformation'] =
573-
server.clientDiagnosticInformation;
574-
}
560+
_collectGeneralData(collectedData, server);
561+
_collectMessageSchedulerData(collectedData);
562+
await _collectProcessData(collectedData);
563+
_collectCommunicationData(collectedData, server);
564+
_collectContextData(collectedData, server);
565+
_collectAnalysisDriverData(collectedData, server);
566+
_collectFileByteStoreTimingData(collectedData, server);
567+
_collectPerformanceData(collectedData, server);
568+
_collectExceptionsData(collectedData, server);
569+
await _collectObservatoryData(collectedData);
575570

576-
collectedData['allowOverlappingHandlers'] =
577-
MessageScheduler.allowOverlappingHandlers;
571+
const JsonEncoder encoder = JsonEncoder.withIndent(' ');
572+
return encoder.convert(collectedData);
573+
}
578574

579-
var profiler = ProcessProfiler.getProfilerForPlatform();
580-
UsageInfo? usage;
581-
if (profiler != null) {
582-
usage = await profiler.getProcessUsage(pid);
583-
}
584-
collectedData['memoryKB'] = usage?.memoryKB;
585-
collectedData['cpuPercentage'] = usage?.cpuPercentage;
586-
collectedData['currentRss'] = ProcessInfo.currentRss;
587-
collectedData['maxRss'] = ProcessInfo.maxRss;
575+
void _collectAnalysisDriverData(
576+
Map<String, Object?> collectedData,
577+
AnalysisServer server,
578+
) {
579+
var buffer = StringBuffer();
580+
server.analysisDriverScheduler.accumulatedPerformance.write(buffer: buffer);
581+
collectedData['accumulatedPerformance'] = buffer.toString();
582+
}
588583

589-
// Communication.
584+
void _collectCommunicationData(
585+
Map<String, Object?> collectedData,
586+
AnalysisServer server,
587+
) {
590588
for (var data
591589
in {
592590
'startup': server.performanceDuringStartup,
@@ -610,16 +608,21 @@ class CollectReportPage extends DiagnosticPage {
610608
perfData['MaximumLatency'] = maximumLatency;
611609
perfData['SlowRequestCount'] = slowRequestCount;
612610
}
611+
}
613612

614-
// Contexts.
613+
void _collectContextData(
614+
Map<String, Object?> collectedData,
615+
AnalysisServer server,
616+
) {
615617
var driverMapValues = server.driverMap.values.toList();
616618
var contexts = [];
617619
collectedData['contexts'] = contexts;
618620
Set<String> uniqueKnownFiles = {};
619621
for (var data in driverMapValues) {
620622
var contextData = {};
621623
contexts.add(contextData);
622-
// We don't include the name as some might see that as "secret".
624+
// We don't include the name because the name might include confidential
625+
// information.
623626
var knownFiles = data.knownFiles.map((f) => f.path).toSet();
624627
contextData['priorityFiles'] = data.priorityFiles.length;
625628
contextData['addedFiles'] = data.addedFiles.length;
@@ -631,85 +634,12 @@ class CollectReportPage extends DiagnosticPage {
631634
contextData['plugins'] = collectedOptionsData.plugins.toList();
632635
}
633636
collectedData['uniqueKnownFiles'] = uniqueKnownFiles.length;
637+
}
634638

635-
// Data from the 'Analysis Driver Timings' page.
636-
var buffer = StringBuffer();
637-
server.analysisDriverScheduler.accumulatedPerformance.write(buffer: buffer);
638-
collectedData['accumulatedPerformance'] = buffer.toString();
639-
640-
// FileByteStore timings
641-
{
642-
var byteStoreTimings =
643-
server.byteStoreTimings
644-
?.where(
645-
(timing) =>
646-
timing.readCount != 0 || timing.readTime != Duration.zero,
647-
)
648-
.toList();
649-
if (byteStoreTimings != null && byteStoreTimings.isNotEmpty) {
650-
var performance = [];
651-
collectedData['byteStoreTimings'] = performance;
652-
for (var i = 0; i < byteStoreTimings.length; i++) {
653-
var timing = byteStoreTimings[i];
654-
if (timing.readCount == 0) {
655-
continue;
656-
}
657-
658-
var nextTiming =
659-
i + 1 < byteStoreTimings.length ? byteStoreTimings[i + 1] : null;
660-
var duration = (nextTiming?.time ?? DateTime.now()).difference(
661-
timing.time,
662-
);
663-
var description =
664-
'Between ${timing.reason} and ${nextTiming?.reason ?? 'now'} '
665-
'(${printMilliseconds(duration.inMilliseconds)}).';
666-
667-
var itemData = {};
668-
performance.add(itemData);
669-
itemData['file_reads'] = timing.readCount;
670-
itemData['time'] = timing.readTime.inMilliseconds;
671-
itemData['description'] = description;
672-
}
673-
}
674-
}
675-
676-
// Recorded performance data (timing and code completion).
677-
void collectPerformance(List<RequestPerformance> items, String type) {
678-
var performance = [];
679-
collectedData['performance$type'] = performance;
680-
for (var item in items) {
681-
var itemData = {};
682-
performance.add(itemData);
683-
itemData['id'] = item.id;
684-
itemData['operation'] = item.operation;
685-
itemData['requestLatency'] = item.requestLatency;
686-
itemData['elapsed'] = item.performance.elapsed.inMilliseconds;
687-
itemData['startTime'] = item.startTime?.toIso8601String();
688-
689-
var buffer = StringBuffer();
690-
item.performance.write(buffer: buffer);
691-
itemData['performance'] = buffer.toString();
692-
}
693-
}
694-
695-
collectPerformance(
696-
server.recentPerformance.completion.items.toList(),
697-
'Completion',
698-
);
699-
collectPerformance(
700-
server.recentPerformance.getFixes.items.toList(),
701-
'GetFixes',
702-
);
703-
collectPerformance(
704-
server.recentPerformance.requests.items.toList(),
705-
'Requests',
706-
);
707-
collectPerformance(
708-
server.recentPerformance.slowRequests.items.toList(),
709-
'SlowRequests',
710-
);
711-
712-
// Exceptions.
639+
void _collectExceptionsData(
640+
Map<String, Object?> collectedData,
641+
AnalysisServer server,
642+
) {
713643
var exceptions = [];
714644
collectedData['exceptions'] = exceptions;
715645
for (var exception in server.exceptions.items) {
@@ -720,8 +650,75 @@ class CollectReportPage extends DiagnosticPage {
720650
'stackTrace': exception.stackTrace.toString(),
721651
});
722652
}
653+
}
654+
655+
void _collectFileByteStoreTimingData(
656+
Map<String, Object?> collectedData,
657+
AnalysisServer server,
658+
) {
659+
var byteStoreTimings =
660+
server.byteStoreTimings
661+
?.where(
662+
(timing) =>
663+
timing.readCount != 0 || timing.readTime != Duration.zero,
664+
)
665+
.toList();
666+
if (byteStoreTimings != null && byteStoreTimings.isNotEmpty) {
667+
var performance = [];
668+
collectedData['byteStoreTimings'] = performance;
669+
for (var i = 0; i < byteStoreTimings.length; i++) {
670+
var timing = byteStoreTimings[i];
671+
if (timing.readCount == 0) {
672+
continue;
673+
}
674+
675+
var nextTiming =
676+
i + 1 < byteStoreTimings.length ? byteStoreTimings[i + 1] : null;
677+
var duration = (nextTiming?.time ?? DateTime.now()).difference(
678+
timing.time,
679+
);
680+
var description =
681+
'Between ${timing.reason} and ${nextTiming?.reason ?? 'now'} '
682+
'(${printMilliseconds(duration.inMilliseconds)}).';
683+
684+
var itemData = {};
685+
performance.add(itemData);
686+
itemData['file_reads'] = timing.readCount;
687+
itemData['time'] = timing.readTime.inMilliseconds;
688+
itemData['description'] = description;
689+
}
690+
}
691+
}
692+
693+
void _collectGeneralData(
694+
Map<String, Object?> collectedData,
695+
AnalysisServer server,
696+
) {
697+
collectedData['currentTime'] = DateTime.now().millisecondsSinceEpoch;
698+
collectedData['operatingSystem'] = Platform.operatingSystem;
699+
collectedData['version'] = Platform.version;
700+
collectedData['clientId'] = server.options.clientId;
701+
collectedData['clientVersion'] = server.options.clientVersion;
702+
collectedData['protocolVersion'] = PROTOCOL_VERSION;
703+
collectedData['serverType'] = server.runtimeType.toString();
704+
collectedData['uptime'] = server.uptime.toString();
705+
if (server is LegacyAnalysisServer) {
706+
collectedData['serverServices'] =
707+
server.serverServices.map((e) => e.toString()).toList();
708+
} else if (server is LspAnalysisServer) {
709+
collectedData['clientDiagnosticInformation'] =
710+
server.clientDiagnosticInformation;
711+
}
712+
}
723713

724-
// Data from the observatory protocol.
714+
void _collectMessageSchedulerData(Map<String, Object?> collectedData) {
715+
collectedData['allowOverlappingHandlers'] =
716+
MessageScheduler.allowOverlappingHandlers;
717+
}
718+
719+
Future<void> _collectObservatoryData(
720+
Map<String, Object?> collectedData,
721+
) async {
725722
var serviceProtocolInfo = await developer.Service.getInfo();
726723
var startedServiceProtocol = false;
727724
if (serviceProtocolInfo.serverUri == null) {
@@ -790,9 +787,57 @@ class CollectReportPage extends DiagnosticPage {
790787
if (startedServiceProtocol) {
791788
await developer.Service.controlWebServer(silenceOutput: true);
792789
}
790+
}
793791

794-
const JsonEncoder encoder = JsonEncoder.withIndent(' ');
795-
return encoder.convert(collectedData);
792+
void _collectPerformanceData(
793+
Map<String, Object?> collectedData,
794+
AnalysisServer server,
795+
) {
796+
collectedData['performanceCompletion'] = _convertPerformance(
797+
server.recentPerformance.completion.items.toList(),
798+
);
799+
collectedData['performanceGetFixes'] = _convertPerformance(
800+
server.recentPerformance.getFixes.items.toList(),
801+
);
802+
collectedData['performanceRequests'] = _convertPerformance(
803+
server.recentPerformance.requests.items.toList(),
804+
);
805+
collectedData['performanceSlowRequests'] = _convertPerformance(
806+
server.recentPerformance.slowRequests.items.toList(),
807+
);
808+
}
809+
810+
Future<void> _collectProcessData(Map<String, Object?> collectedData) async {
811+
var profiler = ProcessProfiler.getProfilerForPlatform();
812+
UsageInfo? usage;
813+
if (profiler != null) {
814+
usage = await profiler.getProcessUsage(pid);
815+
}
816+
collectedData['memoryKB'] = usage?.memoryKB;
817+
collectedData['cpuPercentage'] = usage?.cpuPercentage;
818+
collectedData['currentRss'] = ProcessInfo.currentRss;
819+
collectedData['maxRss'] = ProcessInfo.maxRss;
820+
}
821+
822+
// Recorded performance data (timing and code completion).
823+
List<Object> _convertPerformance(List<RequestPerformance> items) {
824+
var performance = <Object>[];
825+
826+
for (var item in items) {
827+
var itemData = {};
828+
performance.add(itemData);
829+
830+
itemData['id'] = item.id;
831+
itemData['operation'] = item.operation;
832+
itemData['requestLatency'] = item.requestLatency;
833+
itemData['elapsed'] = item.performance.elapsed.inMilliseconds;
834+
itemData['startTime'] = item.startTime?.toIso8601String();
835+
836+
var buffer = StringBuffer();
837+
item.performance.write(buffer: buffer);
838+
itemData['performance'] = buffer.toString();
839+
}
840+
return performance;
796841
}
797842
}
798843

0 commit comments

Comments
 (0)