Measure the startup overhead of different programming languages
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

++

iacore f5a16bab 57718d43

+82 -53
+82 -53
redo.py
··· 1 1 #!/usr/bin/env python 2 2 3 3 """ 4 - A model of dependency graph. A build system. 4 + Concurrent task runner with file mtime tracking. 5 5 6 6 ## Features 7 7 8 - - [X] a rule can have multiple output files 9 - - [ ] run rules lazily 10 - - [X] allow a rule to compute its inputs on startup (already possible with computed property getter) 11 - - [ ] clean files 8 + - [X] a task can have multiple output files 9 + - [X] input files of a task may (already possible with computed property getter) 10 + - [ ] `Task.name` as phony file 11 + - [ ] tasks are run in causal ordering 12 + - [ ] long-running tasks with graceful shutdown 13 + - [ ] allow dependency loop but not build loop 14 + - [ ] clean files (it may break a loop by cleaning it) 12 15 """ 13 16 14 - import abc 17 + import abc, sys, asyncio 15 18 16 - class Rule(abc.ABC): 19 + class Task(abc.ABC): 17 20 input: list[str] 18 21 output: list[str] 19 22 20 - def __init_subclass__(rule, **kwargs): 21 - assert isinstance(rule.input, list), "input must be list[str]" 22 - assert isinstance(rule.output, list), "output must be list[str]" 23 + def __init_subclass__(task, **kwargs): 24 + assert isinstance(task.input, list), "input must be list[str]" 25 + assert isinstance(task.output, list), "output must be list[str]" 23 26 super().__init_subclass__(**kwargs) 24 - register(rule) 27 + register(task) 25 28 26 29 @abc.abstractclassmethod 27 - def build(rule): pass 30 + def build(task): pass 28 31 29 32 30 - def register(rule: Rule): 31 - rule.build() # todo 33 + from os.path import realpath 34 + from collections import defaultdict 32 35 33 - def main(): 34 - # todo 35 - pass 36 + output_to_task: defaultdict[str, set[Task]] = defaultdict(set) 36 37 37 - ## above is build system 38 + def register(task: Task): 39 + for filename in task.output: 40 + output_to_task[realpath(filename)].add(task) 41 + 42 + # def get_task(name: str) -> Task: 43 + 44 + 45 + # def paint(task: Task): 46 + 47 + 48 + async def main(): 49 + # for name in sys.argv[1:]: 50 + # if not output_to_task[realpath(name)]: 51 + # exit("Unable to build) 52 + # targets |= output_to_task[realpath(name)] 53 + 54 + # print(targets) 55 + 56 + for target in targets: 57 + paint(target) 58 + for target in targets: 59 + asyncio.create_task(wash(target), name=target) 60 + 61 + ## above is build system 62 + ## === in karma we trust === 38 63 ## below is build definition 64 + 39 65 40 66 import os 41 67 from subprocess import run 42 68 43 69 44 - class _rule_amd64_asm(Rule): 70 + class _task_amd64_asm(Task): 45 71 input = [ 'true.s' ] 46 72 output = [ './true-s', 'true.o' ] 47 73 48 74 @classmethod 49 - def build(rule): 50 - run(["nasm", "-f", "elf64", rule.input[0]]) 51 - run(["ld", "-o", rule.output[0], rule.output[1]]) 75 + def build(task): 76 + run(["nasm", "-f", "elf64", task.input[0]]) 77 + run(["ld", "-o", task.output[0], task.output[1]]) 52 78 53 79 54 - class _rule_c(Rule): 80 + class _task_c(Task): 55 81 input = [ 'true.c' ] 56 82 output = [ './true-c' ] 57 83 58 84 @classmethod 59 - def build(rule): 60 - run(["gcc", "-O3", "-o", rule.output[0], rule.input[0]]) 85 + def build(task): 86 + run(["gcc", "-O3", "-o", task.output[0], task.input[0]]) 61 87 62 88 63 - class _rule_zig(Rule): 89 + class _task_zig(Task): 64 90 input = [ 'true.zig' ] 65 91 output = [ './true-zig' ] 66 92 67 93 @classmethod 68 - def build(rule): 69 - run(["zig", "build-exe", "-femit-bin=" + rule.output[0], "-O", "ReleaseFast", rule.input[0]]) 94 + def build(task): 95 + run(["zig", "build-exe", "-femit-bin=" + task.output[0], "-O", "ReleaseFast", task.input[0]]) 70 96 71 97 72 - class _rule_hare(Rule): 98 + class _task_hare(Task): 73 99 input = [ 'true.ha' ] 74 100 output = [ './true-hare' ] 75 101 76 102 @classmethod 77 - def build(rule): 78 - run(["hare", "build", "-o", rule.output[0], "-F", "-R", rule.input[0]]) 103 + def build(task): 104 + run(["hare", "build", "-o", task.output[0], "-F", "-R", task.input[0]]) 79 105 80 106 81 - class _rule_go(Rule): 107 + class _task_go(Task): 82 108 input = [ 'true.go' ] 83 109 output = [ './true-go' ] 84 110 85 111 @classmethod 86 - def build(rule): 87 - run(["go", "build", "-o", rule.output[0], rule.input[0]]) 112 + def build(task): 113 + run(["go", "build", "-o", task.output[0], task.input[0]]) 88 114 89 115 90 - class _rule_lean(Rule): 116 + class _task_lean(Task): 91 117 input = [ 'True.lean' ] 92 118 output = [ './true-lean', 'True.c' ] 93 119 94 120 @classmethod 95 - def build(rule): 96 - run(["lean", "-c" + rule.output[1], rule.input[0]]) 97 - run(["leanc", "-O3", "-o", rule.output[0], rule.output[1]]) 121 + def build(task): 122 + run(["lean", "-c" + task.output[1], task.input[0]]) 123 + run(["leanc", "-O3", "-o", task.output[0], task.output[1]]) 98 124 99 125 100 - class _rule_haskell(Rule): 126 + class _task_haskell(Task): 101 127 input = [ 'True.hs' ] 102 128 output = [ './true-haskell' ] 103 129 104 130 @classmethod 105 - def build(rule): 106 - run(["ghc", rule.input[0], "-o", rule.output[0], "-O"]) 131 + def build(task): 132 + run(["ghc", task.input[0], "-o", task.output[0], "-O"]) 107 133 108 134 109 - class _rule_rust(Rule): 135 + class _task_rust(Task): 110 136 input = [ 'true.rs' ] 111 137 output = [ './true-rust' ] 112 138 113 139 @classmethod 114 - def build(rule): 115 - run(["rustc", "-O", "-o", rule.output[0], rule.input[0]]) 140 + def build(task): 141 + run(["rustc", "-O", "-o", task.output[0], task.input[0]]) 116 142 117 143 118 - class _rule_d(Rule): 144 + class _task_d(Task): 119 145 input = [ 'true.d' ] 120 146 output = [ './true-d' ] 121 147 122 148 @classmethod 123 - def build(rule): 124 - run(["dmd", "-O", "-of=" + rule.output[0], rule.input[0]]) 149 + def build(task): 150 + run(["dmd", "-O", "-of=" + task.output[0], task.input[0]]) 125 151 126 152 127 - class _rule_pony(Rule): 153 + class _task_pony(Task): 128 154 input = [ 'true.pony' ] 129 155 output = [ './true-pony' ] 130 156 131 157 @classmethod 132 - def build(rule): 133 - run(["ponyc", "-b", rule.output[0], "."]) 158 + def build(task): 159 + run(["ponyc", "-b", task.output[0], "."]) 134 160 135 161 136 - class _rule_timings(Rule): 162 + class _task_timings(Task): 137 163 input = [ './true-s', './true-c', './true-zig', './true-hare', './true-go', './true-lean', './true-haskell', './true-rust', './true-d', './true-pony' ] 138 164 output = ["timings.md"] 139 165 140 166 @classmethod 141 - def build(rule): 142 - run(["hyperfine", "--export-markdown", rule.output[0], "-N", *rule.input]) 167 + def build(task): 168 + run(["hyperfine", "--export-markdown", task.output[0], "-N", *task.input]) 169 + 170 + if __name__ == '__main__': 171 + asyncio.run(main())