Repository navigation
Scale gcs metrics center write with task name #444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| # 1.0.1 | ||
|
|
||
| - `update` now requires taskName to scale metric writes | ||
|
|
||
| # 1.0.0 | ||
|
|
||
| - Null safety support | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,8 +52,9 @@ class FlutterDestination extends MetricDestination { | |
| } | ||
|
|
||
| @override | ||
| Future<void> update(List<MetricPoint> points, DateTime commitTime) async { | ||
| await _skiaPerfDestination.update(points, commitTime); | ||
| Future<void> update( | ||
| List<MetricPoint> points, DateTime commitTime, String taskName) async { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: metric name is more apt in this context
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Task name is more preferred, as a task contains multiple different metrics and we want to separate values based on different tasks. |
||
| await _skiaPerfDestination.update(points, commitTime, taskName); | ||
| } | ||
|
|
||
| final SkiaPerfDestination _skiaPerfDestination; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -312,12 +312,12 @@ class SkiaPerfGcsAdaptor { | |
| /// (git revision). | ||
| /// | ||
| /// Skia perf needs all directory names to be well formatted. The final name | ||
| /// of the json file (currently `values.json`) can be arbitrary, and multiple | ||
| /// json files can be put in that leaf directory. We intend to use multiple | ||
| /// json files in the future to scale up the system if too many writes are | ||
| /// competing for the same json file. | ||
| static Future<String> computeObjectName( | ||
| String githubRepo, String? revision, DateTime commitTime) async { | ||
| /// of the json file can be arbitrary, and multiple json files can be put | ||
| /// in that leaf directory. We are using multiple json files divided by test | ||
| /// names to scale up the system to avoid too many writes competing for | ||
| /// the same json file. | ||
| static Future<String> computeObjectName(String githubRepo, String? revision, | ||
| DateTime commitTime, String taskName) async { | ||
| assert(_githubRepoToGcsName[githubRepo] != null); | ||
| final String? topComponent = _githubRepoToGcsName[githubRepo]; | ||
| // [commitTime] is not guranteed to be UTC. Ensure it is so all results | ||
|
|
@@ -327,7 +327,7 @@ class SkiaPerfGcsAdaptor { | |
| final String day = commitUtcTime.day.toString().padLeft(2, '0'); | ||
| final String hour = commitUtcTime.hour.toString().padLeft(2, '0'); | ||
| final String dateComponents = '${commitUtcTime.year}/$month/$day/$hour'; | ||
| return '$topComponent/$dateComponents/$revision/values.json'; | ||
| return '$topComponent/$dateComponents/$revision/${taskName}_values.json'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does task name matter? Could we just generate a random id
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it would be more meaningful to include the task name so we can track different values for a specific task. |
||
| } | ||
|
|
||
| static final Map<String, String> _githubRepoToGcsName = <String, String>{ | ||
|
|
@@ -392,7 +392,8 @@ class SkiaPerfDestination extends MetricDestination { | |
| } | ||
|
|
||
| @override | ||
| Future<void> update(List<MetricPoint> points, DateTime commitTime) async { | ||
| Future<void> update( | ||
| List<MetricPoint> points, DateTime commitTime, String taskName) async { | ||
| // 1st, create a map based on git repo, git revision, and point id. Git repo | ||
| // and git revision are the top level components of the Skia perf GCS object | ||
| // name. | ||
|
|
@@ -411,14 +412,13 @@ class SkiaPerfDestination extends MetricDestination { | |
| for (final String repo in pointMap.keys) { | ||
| for (final String? revision in pointMap[repo]!.keys) { | ||
| final String objectName = await SkiaPerfGcsAdaptor.computeObjectName( | ||
| repo, revision, commitTime); | ||
| repo, revision, commitTime, taskName); | ||
| final Map<String, SkiaPerfPoint>? newPoints = pointMap[repo]![revision]; | ||
| // If too many bots are writing the metrics of a git revision into this | ||
| // single json file (with name `objectName`), the contention on the lock | ||
| // might be too high. In that case, break the json file into multiple | ||
| // json files according to bot names or task names. Skia perf read all | ||
| // json files in the directory so one can use arbitrary names for those | ||
| // sharded json file names. | ||
| // Too many bots writing the metrics of a git revision into a single json | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm for this change, but it doesn't make sense why infra runs into this. Is the results directory being cached between runs?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the results are cached anywhere. Different tasks/bots randomly access the file, read and write back. It is strange why the issue pops up after switching logic from cocoon to test runner, but it does sound like lock contention. Hopefully this solves the problem.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see the issue. The recipe implemented retry logic on the entire test runner. Thus, If we're going to implement retries in the recipe, it needs to handle this cleanup. Or we can delete the file if it exists instead. However, it's intentional we fail as it indicates a dirty tree. Preferably, we'd implement retries in the test runner and not the recipe.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a gcs lock on
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah perfect! So the issue is we're uploading values.json directly to GCS? How does that get to skia perf?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are reading With this PR, we are dividing the single json file in gcs to be dependent on task name, so that each task has its own json file and there should not be any contention. Skia perf reads data directly from GCS bucket.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So to verify my understanding, the test runner pushes to GCS, and skia perf pulls from GCS? Then the contention is because we're uploading ~100 results to the same location, correct?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's correct. |
||
| // file will cause high contention on the lock. We use multiple | ||
| // json files according to task names. Skia perf read all json files in | ||
| // the directory so one can use arbitrary names for those sharded json | ||
| // file names. | ||
| _lock!.protectedRun('$objectName.lock', () async { | ||
| final List<SkiaPerfPoint> oldPoints = | ||
| await _gcs.readPoints(objectName); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.