-
-
Notifications
You must be signed in to change notification settings - Fork 631
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Check for
@rule
graph cycles asynchronously (#13370)
In pathological cases of very small `@rule` bodies or extreme graph shapes, cycle detection in the `Graph` can be very expensive. This cost can be challenging to detect in production, but it does occasionally show up as hot, particularly while cleaning graphs (since that skips all `@rule` logic). That's precisely when we do not want to be spending any extraneous time on formalities. This change moves to asynchronously checking for cycles in Running nodes in the `Graph`. Checking in the background has two advantages: 1. cycle detection is batched across the entire graph, rather than per-edge-addition, and 2. in most cases, successful Nodes never need to be checked while running. We also add two pathological graph shape benchmarks, which show significant improvement: * `main`: ``` Benchmark #1: ./pants test --force --no-pytest-timeouts src/python/pants/engine/internals/engine_benchmarks_test.py Time (mean ± σ): 247.157 s ± 9.095 s [User: 872.4 ms, System: 305.2 ms] Range (min … max): 240.523 s … 266.031 s 10 runs ``` * this branch: ``` Benchmark #1: ./pants test --force --no-pytest-timeouts src/python/pants/engine/internals/engine_benchmarks_test.py Time (mean ± σ): 34.779 s ± 4.625 s [User: 889.1 ms, System: 303.5 ms] Range (min … max): 32.246 s … 47.491 s 10 runs ```
- Loading branch information
Showing
9 changed files
with
291 additions
and
387 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
src/python/pants/engine/internals/engine_benchmarks_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from dataclasses import dataclass | ||
from random import randrange | ||
|
||
from pants.engine.rules import Get, MultiGet, rule | ||
from pants.testutil.rule_runner import QueryRule, RuleRunner | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Deep: | ||
val: int | ||
|
||
|
||
@rule | ||
async def deep(n: int) -> Deep: | ||
if n < 2: | ||
return Deep(n) | ||
x, y = tuple(await MultiGet([Get(Deep, int(n - 2)), Get(Deep, int(n - 1))])) | ||
return Deep(x.val + y.val) | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Wide: | ||
val: int | ||
|
||
|
||
@rule | ||
async def wide(index: int) -> Wide: | ||
if index > 0: | ||
_ = await MultiGet([Get(Wide, int(randrange(index))) for _ in range(100)]) | ||
return Wide(index) | ||
|
||
|
||
def test_bench_deep(): | ||
rule_runner = RuleRunner(rules=[deep, QueryRule(Deep, (int,))]) | ||
for _ in range(0, 10): | ||
rule_runner.scheduler.scheduler.invalidate_all() | ||
_ = rule_runner.request(Deep, [10000]) | ||
|
||
|
||
def test_bench_wide(): | ||
rule_runner = RuleRunner(rules=[wide, QueryRule(Wide, (int,))]) | ||
for _ in range(0, 5): | ||
rule_runner.scheduler.scheduler.invalidate_all() | ||
_ = rule_runner.request(Wide, [1000]) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.