performance/drop_in_bang.bend
bend-lint-rules@0.2.0.0 · 75 lines · 5 definitions
1
2
3
4
5
6
7
8
9import Base
10import bend-lint-api@0.2.0.0/linter/lint.bend as Lint
11import bend-lint-api@0.2.0.0/shared/names.bend as Names
12import bend-lint-rules@0.2.0.0/performance/gpu_fit.bend as GpuFit
13
14
15
16
17
18
19type Program is Data:
20 Program{defs: Map<&2, Maybe<&2, Lint.Def>>, bangs: List<&2, U32>}
21
22
23
24def message(callee: String) -> String:
25 callee
26 ++ "! only frees what it receives, as it returns Unit, and a GPU frees slower than its CPU. GPU: measured 15x slower than without the `!` on a discrete GPU (CUDA), dropping a 1M-leaf image; with unified memory (Apple M-series), freeing a scene in a bang made a frame 12.9 ms, against 8.0 ms (\"bend guide shaders\"). CPU (`--gpu off`): 10% slower. JS: no GPU, so no change. Confidence: high, as a GPU does not speed up freeing. Remove the `!`; to drop the last frame, let the next frame's fork tree drop it, a quadrant per tile (\"bend guide shaders\"). If a timing shows the `!` faster here, expect this finding."
27
28
29def visit(
30 +program: Program,
31 +path: List<&2, Lint.Above>,
32 +node: Lint.Node
33) -> List<&2, Lint.Finding>:
34 match program node:
35 case Program{
36 defs,
37 bangs
38 } Lint.Node{
39 Lint.Application{},
40 n,
41 span,
42 Con{Lint.Node{Lint.Reference{+t}, callee, Some{Lint.Span{p, beg, end}}, k, f}, args},
43 facts
44 }:
45 Lint.finding(
46 Lint.Warning{},
47 List.contains(
48 ~U32,
49 ~U32.is_eq,
50 bangs,
51 end
52 )
53 && GpuFit.is_drop(Names.find(Lint.Def, defs, t), t),
54 span,
55 message(callee)
56 )
57 case _ _:
58 []
59
60def run(+here: Lint.Here) -> Lint.Ask(List<&2, Lint.Finding>):
61 Lint.done(
62 Lint.visit(
63 ~Program,
64 ~Lint.Finding,
65 ~visit,
66 Program{
67 Lint.Program.defs(Lint.Here.sources(here), Map.new(&2, Maybe<&2, Lint.Def>)),
68 GpuFit.bangs(Lint.Here.text(here), 0, [])
69 },
70 Lint.Here.nodes(here)
71 )
72 )
73
74def rule() -> Lint.Rule:
75 Lint.Rule{Lint.Needs{False{}, False{}}, [], Lint.OnFile{run}}