Skip to content

Commit 4e521db

Browse files
authored
v3: speed up self compilation (#27531)
1 parent 8520724 commit 4e521db

18 files changed

Lines changed: 1631 additions & 133 deletions

File tree

vlib/v3/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ function pointers.
180180
| cc | 79 ms | 17,312 KB |
181181
| **total** | **~259 ms** | **17,312 KB** |
182182

183-
All v3 steps (parse + check + transform + annotate types + markused + gen +
183+
All v3 steps (parse + check + markused + transform + annotate types + gen +
184184
write) complete in ~8 ms for hello world, including 38 builtin files, and
185185
~157 ms for `test.v` with the C backend.
186186

@@ -203,14 +203,14 @@ falls back to `cc`.
203203

204204
| Phase | Time | Peak RSS |
205205
|----------------|----------:|---------:|
206-
| parse | 47.33 ms | 73 MB |
207-
| check | 43.92 ms | 131 MB |
208-
| transform | 94.83 ms | 274 MB |
209-
| annotate types | 30.46 ms | 307 MB |
210-
| markused | 48.53 ms | 354 MB |
211-
| gen C/write | 94.67 ms | 455 MB |
212-
| cc | 707.84 ms | 455 MB |
213-
| **total** | **1,092.92 ms** | **455 MB** |
206+
| parse | 59.47 ms | 73 MB |
207+
| check | 46.57 ms | 126 MB |
208+
| markused | 39.81 ms | 150 MB |
209+
| transform | 70.79 ms | 277 MB |
210+
| annotate types | 25.05 ms | 309 MB |
211+
| gen C/write | 53.75 ms | 353 MB |
212+
| cc | 746.53 ms | 353 MB |
213+
| **total** | **1,042.14 ms** | **353 MB** |
214214

215215
## Comparison with V1
216216

vlib/v3/bench/bench.v

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ module bench
33
import os
44
import time
55

6+
#include <sys/resource.h>
7+
8+
struct C.rusage {
9+
ru_maxrss i64
10+
}
11+
12+
fn C.getrusage(who int, usage &C.rusage) int
13+
614
pub struct Step {
715
pub:
816
name string
@@ -45,18 +53,18 @@ pub fn (b &Bench) print_report() {
4553

4654
fn current_rss_kb() i64 {
4755
$if macos {
48-
return macos_rss_kb()
56+
return macos_peak_rss_kb()
4957
}
5058
$if linux {
5159
return linux_rss_kb()
5260
}
5361
return 0
5462
}
5563

56-
fn macos_rss_kb() i64 {
57-
result := os.execute('ps -o rss= -p ${C.getpid()}')
58-
if result.exit_code == 0 {
59-
return result.output.trim_space().i64()
64+
fn macos_peak_rss_kb() i64 {
65+
mut usage := C.rusage{}
66+
if C.getrusage(0, &usage) == 0 {
67+
return usage.ru_maxrss / 1024
6068
}
6169
return 0
6270
}
@@ -73,5 +81,3 @@ fn linux_rss_kb() i64 {
7381
}
7482
return 0
7583
}
76-
77-
fn C.getpid() int

vlib/v3/gen/c/array.v

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,19 @@ fn (mut g FlatGen) array_method_fallback(method string) string {
305305
return best_mname
306306
}
307307

308-
fn (mut g FlatGen) gen_map_delete(node flat.Node, fn_node &flat.Node, m types.Map) {
308+
fn (mut g FlatGen) gen_map_ref_arg(base_id flat.NodeId, base_type types.Type) {
309+
if base_type is types.Pointer {
310+
g.gen_expr(base_id)
311+
} else {
312+
g.write('&')
313+
g.gen_expr(base_id)
314+
}
315+
}
316+
317+
fn (mut g FlatGen) gen_map_delete(node flat.Node, fn_node &flat.Node, m types.Map, base_type types.Type) {
309318
c_key := g.tc.c_type(m.key_type)
310-
g.write('map__delete(&')
311-
g.gen_expr(g.a.child(fn_node, 0))
319+
g.write('map__delete(')
320+
g.gen_map_ref_arg(g.a.child(fn_node, 0), base_type)
312321
g.write(', &(${c_key}[]){')
313322
g.gen_expr(g.a.child(&node, 1))
314323
g.write('})')

vlib/v3/gen/c/fn.v

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -581,16 +581,16 @@ fn (mut g FlatGen) gen_call(id flat.NodeId, node flat.Node) {
581581
}
582582
if clean_type is types.Map {
583583
if fn_node.value == 'delete' {
584-
g.gen_map_delete(node, fn_node, clean_type)
584+
g.gen_map_delete(node, fn_node, clean_type, base_type)
585585
return
586586
} else if fn_node.value == 'clone' {
587-
g.write('map__clone(&')
588-
g.gen_expr(g.a.child(fn_node, 0))
587+
g.write('map__clone(')
588+
g.gen_map_ref_arg(g.a.child(fn_node, 0), base_type)
589589
g.write(')')
590590
return
591591
} else if fn_node.value == 'clear' {
592-
g.write('map__clear(&')
593-
g.gen_expr(g.a.child(fn_node, 0))
592+
g.write('map__clear(')
593+
g.gen_map_ref_arg(g.a.child(fn_node, 0), base_type)
594594
g.write(')')
595595
return
596596
} else if fn_node.value == 'free' {
@@ -725,16 +725,16 @@ fn (mut g FlatGen) gen_call(id flat.NodeId, node flat.Node) {
725725
}
726726
if clean_type is types.Map {
727727
if fn_node.value == 'delete' {
728-
g.gen_map_delete(node, fn_node, clean_type)
728+
g.gen_map_delete(node, fn_node, clean_type, base_type)
729729
return
730730
} else if fn_node.value == 'clone' {
731-
g.write('map__clone(&')
732-
g.gen_expr(g.a.child(fn_node, 0))
731+
g.write('map__clone(')
732+
g.gen_map_ref_arg(g.a.child(fn_node, 0), base_type)
733733
g.write(')')
734734
return
735735
} else if fn_node.value == 'clear' {
736-
g.write('map__clear(&')
737-
g.gen_expr(g.a.child(fn_node, 0))
736+
g.write('map__clear(')
737+
g.gen_map_ref_arg(g.a.child(fn_node, 0), base_type)
738738
g.write(')')
739739
return
740740
} else if fn_node.value == 'free' {

vlib/v3/gen/c/names.v

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module c
22

3+
import strings
4+
35
const c_reserved_words = ['auto', 'break', 'case', 'char', 'const', 'continue', 'copy', 'default',
46
'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', 'int', 'long',
57
'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
@@ -19,15 +21,105 @@ fn c_name(name string) string {
1921
if name == 'exit' {
2022
return 'v_exit'
2123
}
22-
n := name.replace('[]', 'Array_').replace('.-', '__minus').replace('.+', '__plus').replace('.==',
23-
'__eq').replace('.!=', '__ne').replace('.<=', '__le').replace('.>=', '__ge').replace('.<',
24-
'__lt').replace('.>', '__gt').replace('&', 'ptr').replace('[', '_').replace(']', '').replace(',', '_').replace(' ', '_').replace('.', '__')
24+
if c_name_is_plain(name) {
25+
if name in c_reserved_words {
26+
return 'v_${name}'
27+
}
28+
return name
29+
}
30+
n := c_name_sanitize(name)
2531
if n in c_reserved_words {
2632
return 'v_${n}'
2733
}
2834
return n
2935
}
3036

37+
fn c_name_sanitize(name string) string {
38+
mut b := strings.new_builder(name.len + 8)
39+
mut i := 0
40+
for i < name.len {
41+
c := name[i]
42+
if c == `[` {
43+
if i + 1 < name.len && name[i + 1] == `]` {
44+
b.write_string('Array_')
45+
i += 2
46+
continue
47+
}
48+
b.write_u8(`_`)
49+
} else if c == `]` {
50+
i++
51+
continue
52+
} else if c == `.` {
53+
if i + 1 < name.len {
54+
next := name[i + 1]
55+
if next == `-` {
56+
b.write_string('__minus')
57+
i += 2
58+
continue
59+
}
60+
if next == `+` {
61+
b.write_string('__plus')
62+
i += 2
63+
continue
64+
}
65+
if i + 2 < name.len {
66+
op := name[i + 2]
67+
if next == `=` && op == `=` {
68+
b.write_string('__eq')
69+
i += 3
70+
continue
71+
}
72+
if next == `!` && op == `=` {
73+
b.write_string('__ne')
74+
i += 3
75+
continue
76+
}
77+
if next == `<` && op == `=` {
78+
b.write_string('__le')
79+
i += 3
80+
continue
81+
}
82+
if next == `>` && op == `=` {
83+
b.write_string('__ge')
84+
i += 3
85+
continue
86+
}
87+
}
88+
if next == `<` {
89+
b.write_string('__lt')
90+
i += 2
91+
continue
92+
}
93+
if next == `>` {
94+
b.write_string('__gt')
95+
i += 2
96+
continue
97+
}
98+
}
99+
b.write_string('__')
100+
} else if c == `&` {
101+
b.write_string('ptr')
102+
} else if c == `,` || c == ` ` {
103+
b.write_u8(`_`)
104+
} else {
105+
b.write_u8(c)
106+
}
107+
i++
108+
}
109+
return b.str()
110+
}
111+
112+
fn c_name_is_plain(name string) bool {
113+
for i in 0 .. name.len {
114+
c := name[i]
115+
if (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || (c >= `0` && c <= `9`) || c == `_` {
116+
continue
117+
}
118+
return false
119+
}
120+
return true
121+
}
122+
31123
fn c_escape(s string) string {
32124
return s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\t', '\\t').replace('\r',
33125
'\\r')

vlib/v3/gen/c/names_test.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module c
2+
3+
fn test_c_name_sanitize_operator_overloads() {
4+
assert c_name('Point.<') == 'Point__lt'
5+
assert c_name('Point.<=') == 'Point__le'
6+
assert c_name('Point.>') == 'Point__gt'
7+
assert c_name('Point.>=') == 'Point__ge'
8+
}

0 commit comments

Comments
 (0)