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 9f7e54c8 0e0903a3

+62 -29
+62 -29
redo.py
··· 5 5 6 6 ## Features 7 7 8 - - [X] a task can have multiple output files 9 - - [X] input files of a task may (already possible with computed property getter) 8 + - [xv] a task can have multiple output files 9 + - [x] input files of a task may (already possible with computed property getter) 10 + - [x] tasks are run in causal ordering 11 + - [ ] detect conflicting rules that write to the same file (given a certain set of files to build) 10 12 - [ ] `Task.name` as phony file 11 - - [ ] tasks are run in causal ordering 12 - - [ ] long-running tasks with graceful shutdown 13 + - [ ] watch mode 13 14 - [ ] allow dependency loop but not build loop 14 15 - [ ] clean files (it may break a loop by cleaning it) 16 + 17 + ## Build graph order 18 + 19 + 1. needed 20 + 2. fresh 21 + 3. build task 15 22 """ 16 23 17 24 import abc, sys, asyncio 18 25 26 + class File: 27 + needed : asyncio.Condition 28 + 29 + """ 30 + depends on if this file is a source file (not generated) 31 + if it is source, this is by default true 32 + 33 + this `Condition` depends on `self.needed` 34 + when all input are fresh, the corresponding build command runs 35 + """ 36 + fresh : asyncio.Condition 37 + 38 + def __init__(self): 39 + self.needed = asyncio.Condition() 40 + self.fresh = asyncio.Condition() 41 + 42 + from collections import defaultdict 43 + 44 + files : defaultdict[str, File] = defaultdict(File) 45 + 19 46 class Task(abc.ABC): 20 47 input: list[str] 21 48 output: list[str] ··· 27 54 register(task) 28 55 29 56 @abc.abstractclassmethod 30 - def build(task): pass 57 + def build(self): pass 31 58 59 + async def run(self): 60 + await self.set_dirty() 61 + await self.wait_for_barrier() 62 + await self.wait_for_opportunity() 63 + await asyncio.get_running_loop().run_in_executor(None, self.build) 64 + await self.set_clean() 32 65 33 66 from os.path import realpath 34 67 from collections import defaultdict ··· 72 105 output = [ './true-s', 'true.o' ] 73 106 74 107 @classmethod 75 - def build(task): 76 - run(["nasm", "-f", "elf64", task.input[0]]) 77 - run(["ld", "-o", task.output[0], task.output[1]]) 108 + def build(self): 109 + run(["nasm", "-f", "elf64", self.input[0]]) 110 + run(["ld", "-o", self.output[0], self.output[1]]) 78 111 79 112 80 113 class _task_c(Task): ··· 82 115 output = [ './true-c' ] 83 116 84 117 @classmethod 85 - def build(task): 86 - run(["gcc", "-O3", "-o", task.output[0], task.input[0]]) 118 + def build(self): 119 + run(["gcc", "-O3", "-o", self.output[0], self.input[0]]) 87 120 88 121 89 122 class _task_zig(Task): ··· 91 124 output = [ './true-zig' ] 92 125 93 126 @classmethod 94 - def build(task): 95 - run(["zig", "build-exe", "-femit-bin=" + task.output[0], "-O", "ReleaseFast", task.input[0]]) 127 + def build(self): 128 + run(["zig", "build-exe", "-femit-bin=" + self.output[0], "-O", "ReleaseFast", self.input[0]]) 96 129 97 130 98 131 class _task_hare(Task): ··· 100 133 output = [ './true-hare' ] 101 134 102 135 @classmethod 103 - def build(task): 104 - run(["hare", "build", "-o", task.output[0], "-F", "-R", task.input[0]]) 136 + def build(self): 137 + run(["hare", "build", "-o", self.output[0], "-F", "-R", self.input[0]]) 105 138 106 139 107 140 class _task_go(Task): ··· 109 142 output = [ './true-go' ] 110 143 111 144 @classmethod 112 - def build(task): 113 - run(["go", "build", "-o", task.output[0], task.input[0]]) 145 + def build(self): 146 + run(["go", "build", "-o", self.output[0], self.input[0]]) 114 147 115 148 116 149 class _task_lean(Task): ··· 118 151 output = [ './true-lean', 'True.c' ] 119 152 120 153 @classmethod 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]]) 154 + def build(self): 155 + run(["lean", "-c" + self.output[1], self.input[0]]) 156 + run(["leanc", "-O3", "-o", self.output[0], self.output[1]]) 124 157 125 158 126 159 class _task_haskell(Task): ··· 128 161 output = [ './true-haskell' ] 129 162 130 163 @classmethod 131 - def build(task): 132 - run(["ghc", task.input[0], "-o", task.output[0], "-O"]) 164 + def build(self): 165 + run(["ghc", self.input[0], "-o", self.output[0], "-O"]) 133 166 134 167 135 168 class _task_rust(Task): ··· 137 170 output = [ './true-rust' ] 138 171 139 172 @classmethod 140 - def build(task): 141 - run(["rustc", "-O", "-o", task.output[0], task.input[0]]) 173 + def build(self): 174 + run(["rustc", "-O", "-o", self.output[0], self.input[0]]) 142 175 143 176 144 177 class _task_d(Task): ··· 146 179 output = [ './true-d' ] 147 180 148 181 @classmethod 149 - def build(task): 150 - run(["dmd", "-O", "-of=" + task.output[0], task.input[0]]) 182 + def build(self): 183 + run(["dmd", "-O", "-of=" + self.output[0], self.input[0]]) 151 184 152 185 153 186 class _task_pony(Task): ··· 155 188 output = [ './true-pony' ] 156 189 157 190 @classmethod 158 - def build(task): 159 - run(["ponyc", "-b", task.output[0], "."]) 191 + def build(self): 192 + run(["ponyc", "-b", self.output[0], "."]) 160 193 161 194 162 195 class _task_timings(Task): ··· 164 197 output = ["timings.md"] 165 198 166 199 @classmethod 167 - def build(task): 168 - run(["hyperfine", "--export-markdown", task.output[0], "-N", *task.input]) 200 + def build(self): 201 + run(["hyperfine", "--export-markdown", self.output[0], "-N", *self.input]) 169 202 170 203 if __name__ == '__main__': 171 204 asyncio.run(main())