Introduce and use a new class to compute the mean reciprocal rank after a run of the code completion metrics execution.
Change-Id: I72ee7fdc500d6310231b3b03a2722e63feee251a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133439
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Jaime Wren <jwren@google.com>
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index 88a392f..629549a 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -47,6 +47,7 @@
var completionKindCounter = Counter('completion kind counter');
var completionElementKindCounter =
Counter('completion element kind counter');
+ var mRRComputer = MeanReciprocalRankComputer();
print('Analyzing root: \"$_rootPath\"');
@@ -84,13 +85,20 @@
expectedCompletion.offset,
declarationsTracker);
- var fraction =
+ var place =
_placementInSuggestionList(suggestions, expectedCompletion);
- if (fraction.denominator != 0) {
+ mRRComputer.addReciprocalRank(place);
+
+ if (place.denominator != 0) {
includedCount++;
} else {
notIncludedCount++;
+
+ completionKindCounter.count(expectedCompletion.kind.toString());
+ completionElementKindCounter
+ .count(expectedCompletion.elementKind.toString());
+
if (_verbose) {
// The format "/file/path/foo.dart:3:4" makes for easier input
// with the Files dialog in IntelliJ
@@ -99,11 +107,6 @@
print(
'\tdid not include the expected completion: \"${expectedCompletion.completion}\", completion kind: ${expectedCompletion.kind.toString()}, element kind: ${expectedCompletion.elementKind.toString()}');
print('');
-
- completionKindCounter
- .count(expectedCompletion.kind.toString());
- completionElementKindCounter
- .count(expectedCompletion.elementKind.toString());
}
}
}
@@ -120,7 +123,14 @@
final percentNotIncluded = 1 - percentIncluded;
completionKindCounter.printCounterValues();
+ print('');
+
completionElementKindCounter.printCounterValues();
+ print('');
+
+ mRRComputer.printMean();
+ print('');
+
print('Summary for $_rootPath:');
print('Total number of completion tests = $totalCompletionCount');
print(
@@ -132,6 +142,7 @@
notIncludedCount = 0;
completionKindCounter.clear();
completionElementKindCounter.clear();
+ mRRComputer.clear();
}
Future<List<CompletionSuggestion>> _computeCompletionSuggestions(
diff --git a/pkg/analysis_server/tool/completion_metrics/metrics_util.dart b/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
index cf7ddbe..30450de 100644
--- a/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
+++ b/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
@@ -52,7 +52,37 @@
print('Counts for \'$name\':');
_buckets.forEach((id, count) =>
print('[$id] $count (${printPercentage(count / _totalCount, 2)})'));
- print('');
+ }
+}
+
+/// A computer for the mean reciprocal rank,
+/// https://en.wikipedia.org/wiki/Mean_reciprocal_rank.
+class MeanReciprocalRankComputer {
+ final List<double> _ranks = [];
+ MeanReciprocalRankComputer();
+
+ double get mean {
+ double sum = 0;
+ _ranks.forEach((rank) {
+ sum += rank;
+ });
+ return rankCount == 0 ? 0 : sum / rankCount;
+ }
+
+ int get rankCount => _ranks.length;
+
+ int get ranks => _ranks.length;
+
+ void addReciprocalRank(Place place) {
+ _ranks.add(place.reciprocalRank);
+ }
+
+ void clear() => _ranks.clear();
+
+ void printMean() {
+ var mrr = mean;
+ print('Mean Reciprocal Rank = ${mrr.toStringAsFixed(5)}');
+ print('Harmonic Mean (inverse) = ${(1 / mrr).toStringAsFixed(1)}');
}
}
@@ -80,6 +110,8 @@
int get numerator => _numerator;
+ double get reciprocalRank => denominator == 0 ? 0 : numerator / denominator;
+
@override
bool operator ==(dynamic other) =>
other is Place &&