1- use codeinput:: core:: parser:: parse_line;
2- use criterion:: { Criterion , black_box, criterion_group, criterion_main} ;
1+ use codeinput:: core:: parser:: { parse_codeowners, parse_line, parse_owner} ;
2+ use criterion:: { Criterion , criterion_group, criterion_main} ;
3+ use std:: hint:: black_box;
4+ use std:: io:: Write ;
35use std:: path:: Path ;
6+ use tempfile:: NamedTempFile ;
47
8+ // parse_codeowners benchmark
9+ fn bench_parse_codeowners_small_file ( c : & mut Criterion ) {
10+ let mut temp_file = NamedTempFile :: new ( ) . unwrap ( ) ;
11+ writeln ! ( temp_file, "# Small CODEOWNERS file" ) . unwrap ( ) ;
12+ writeln ! ( temp_file, "*.js @frontend-team" ) . unwrap ( ) ;
13+ writeln ! ( temp_file, "*.rs @backend-team" ) . unwrap ( ) ;
14+ writeln ! ( temp_file, "/docs/ @docs-team #documentation" ) . unwrap ( ) ;
15+ writeln ! ( temp_file, "*.md @org/writers user@example.com #content" ) . unwrap ( ) ;
16+ temp_file. flush ( ) . unwrap ( ) ;
17+
18+ c. bench_function ( "parse_codeowners_small" , |b| {
19+ b. iter ( || parse_codeowners ( black_box ( temp_file. path ( ) ) ) . unwrap ( ) )
20+ } ) ;
21+ }
22+
23+ fn bench_parse_codeowners_medium_file ( c : & mut Criterion ) {
24+ let mut temp_file = NamedTempFile :: new ( ) . unwrap ( ) ;
25+ writeln ! ( temp_file, "# Medium CODEOWNERS file with various patterns" ) . unwrap ( ) ;
26+ writeln ! ( temp_file) . unwrap ( ) ;
27+ writeln ! ( temp_file, "# Global owners" ) . unwrap ( ) ;
28+ writeln ! ( temp_file, "* @org/global-team" ) . unwrap ( ) ;
29+ writeln ! ( temp_file) . unwrap ( ) ;
30+ writeln ! ( temp_file, "# Frontend" ) . unwrap ( ) ;
31+ writeln ! ( temp_file, "*.js @frontend-team @alice #frontend" ) . unwrap ( ) ;
32+ writeln ! ( temp_file, "*.ts @frontend-team @bob #frontend #typescript" ) . unwrap ( ) ;
33+ writeln ! ( temp_file, "*.tsx @org/react-team user@react.com #ui #react" ) . unwrap ( ) ;
34+ writeln ! ( temp_file, "*.vue @org/vue-team #frontend #vue" ) . unwrap ( ) ;
35+ writeln ! ( temp_file, "/src/components/ @org/ui-team #components" ) . unwrap ( ) ;
36+ writeln ! ( temp_file, "/src/pages/ @org/frontend @charlie #pages" ) . unwrap ( ) ;
37+ writeln ! ( temp_file) . unwrap ( ) ;
38+ writeln ! ( temp_file, "# Backend" ) . unwrap ( ) ;
39+ writeln ! ( temp_file, "*.rs @backend-team @dave #backend #rust" ) . unwrap ( ) ;
40+ writeln ! (
41+ temp_file,
42+ "*.go @org/go-team engineer@backend.com #backend #go"
43+ )
44+ . unwrap ( ) ;
45+ writeln ! ( temp_file, "*.py @org/python-team #backend #python" ) . unwrap ( ) ;
46+ writeln ! ( temp_file, "/src/api/ @org/api-team #api" ) . unwrap ( ) ;
47+ writeln ! ( temp_file, "/src/database/ @org/db-team @eve #database" ) . unwrap ( ) ;
48+ writeln ! ( temp_file) . unwrap ( ) ;
49+ writeln ! ( temp_file, "# Infrastructure" ) . unwrap ( ) ;
50+ writeln ! ( temp_file, "Dockerfile @org/devops #docker #infrastructure" ) . unwrap ( ) ;
51+ writeln ! ( temp_file, "*.yml @org/devops @frank #ci #infrastructure" ) . unwrap ( ) ;
52+ writeln ! ( temp_file, "*.yaml @org/devops #ci #infrastructure" ) . unwrap ( ) ;
53+ writeln ! (
54+ temp_file,
55+ "/terraform/ @org/infrastructure #terraform #infrastructure"
56+ )
57+ . unwrap ( ) ;
58+ writeln ! ( temp_file, "/k8s/ @org/k8s-team ops@company.com #kubernetes" ) . unwrap ( ) ;
59+ writeln ! ( temp_file) . unwrap ( ) ;
60+ writeln ! ( temp_file, "# Documentation" ) . unwrap ( ) ;
61+ writeln ! ( temp_file, "*.md @docs-team @grace #documentation" ) . unwrap ( ) ;
62+ writeln ! ( temp_file, "/docs/ @org/tech-writers #documentation" ) . unwrap ( ) ;
63+ writeln ! ( temp_file, "README.md @org/maintainers #readme" ) . unwrap ( ) ;
64+ temp_file. flush ( ) . unwrap ( ) ;
65+
66+ c. bench_function ( "parse_codeowners_medium" , |b| {
67+ b. iter ( || parse_codeowners ( black_box ( temp_file. path ( ) ) ) . unwrap ( ) )
68+ } ) ;
69+ }
70+
71+ fn bench_parse_codeowners_complex_file ( c : & mut Criterion ) {
72+ let mut temp_file = NamedTempFile :: new ( ) . unwrap ( ) ;
73+ writeln ! (
74+ temp_file,
75+ "# Complex CODEOWNERS file with many patterns and edge cases"
76+ )
77+ . unwrap ( ) ;
78+ writeln ! ( temp_file) . unwrap ( ) ;
79+ writeln ! ( temp_file, "# Global fallback" ) . unwrap ( ) ;
80+ writeln ! ( temp_file, "* @org/global-maintainers NOOWNER" ) . unwrap ( ) ;
81+ writeln ! ( temp_file) . unwrap ( ) ;
82+ writeln ! ( temp_file, "# Frontend microservices" ) . unwrap ( ) ;
83+ writeln ! ( temp_file, "/services/web-app/**/*.js @org/web-frontend @alice @bob user1@frontend.com #frontend #webapp" ) . unwrap ( ) ;
84+ writeln ! ( temp_file, "/services/web-app/**/*.ts @org/web-frontend @charlie engineer@webapp.com #frontend #typescript #webapp" ) . unwrap ( ) ;
85+ writeln ! ( temp_file, "/services/mobile-app/**/*.tsx @org/mobile-team @dave @eve mobile@company.com #mobile #react-native" ) . unwrap ( ) ;
86+ writeln ! (
87+ temp_file,
88+ "/services/admin-portal/**/*.vue @org/admin-team admin@company.com #admin #vue #portal"
89+ )
90+ . unwrap ( ) ;
91+ writeln ! ( temp_file) . unwrap ( ) ;
92+ writeln ! ( temp_file, "# Backend services" ) . unwrap ( ) ;
93+ writeln ! ( temp_file, "/services/user-service/**/*.rs @org/user-team @frank backend1@company.com #backend #rust #users" ) . unwrap ( ) ;
94+ writeln ! ( temp_file, "/services/payment-service/**/*.go @org/payments @grace @henry payments@company.com #backend #go #payments #critical" ) . unwrap ( ) ;
95+ writeln ! ( temp_file, "/services/notification-service/**/*.py @org/notifications notifications@company.com #backend #python #notifications" ) . unwrap ( ) ;
96+ writeln ! ( temp_file, "/services/analytics-service/**/*.scala @org/analytics @ivan analytics@company.com #backend #scala #analytics" ) . unwrap ( ) ;
97+ writeln ! ( temp_file) . unwrap ( ) ;
98+ writeln ! ( temp_file, "# Infrastructure and DevOps" ) . unwrap ( ) ;
99+ writeln ! ( temp_file, "/infrastructure/terraform/**/*.tf @org/infrastructure @jack @kate infra@company.com #terraform #infrastructure #critical" ) . unwrap ( ) ;
100+ writeln ! ( temp_file, "/infrastructure/k8s/**/*.yaml @org/k8s-team @liam k8s@company.com #kubernetes #infrastructure" ) . unwrap ( ) ;
101+ writeln ! ( temp_file, "/infrastructure/monitoring/**/*.yml @org/monitoring @mike monitoring@company.com #monitoring #infrastructure" ) . unwrap ( ) ;
102+ writeln ! (
103+ temp_file,
104+ "/.github/workflows/**/*.yml @org/ci-cd @nina @oscar ci@company.com #ci #github-actions"
105+ )
106+ . unwrap ( ) ;
107+ writeln ! ( temp_file) . unwrap ( ) ;
108+ writeln ! ( temp_file, "# Security and compliance" ) . unwrap ( ) ;
109+ writeln ! (
110+ temp_file,
111+ "/security/**/* @org/security @paul @quinn security@company.com #security #critical"
112+ )
113+ . unwrap ( ) ;
114+ writeln ! (
115+ temp_file,
116+ "/**/*secret* @org/security security@company.com #security #secrets #critical"
117+ )
118+ . unwrap ( ) ;
119+ writeln ! (
120+ temp_file,
121+ "/**/*key* @org/security #security #secrets #critical"
122+ )
123+ . unwrap ( ) ;
124+ writeln ! (
125+ temp_file,
126+ "/compliance/**/*.json @org/compliance @rachel compliance@company.com #compliance #audit"
127+ )
128+ . unwrap ( ) ;
129+ writeln ! ( temp_file) . unwrap ( ) ;
130+ writeln ! ( temp_file, "# Database and migrations" ) . unwrap ( ) ;
131+ writeln ! ( temp_file, "/database/migrations/**/*.sql @org/db-team @steve @tina db@company.com #database #migrations #critical" ) . unwrap ( ) ;
132+ writeln ! ( temp_file, "/database/schemas/**/*.sql @org/db-architects db-arch@company.com #database #schema #critical" ) . unwrap ( ) ;
133+ writeln ! ( temp_file) . unwrap ( ) ;
134+ writeln ! ( temp_file, "# Documentation and configuration" ) . unwrap ( ) ;
135+ writeln ! (
136+ temp_file,
137+ "/docs/**/*.md @org/tech-writers @uma docs@company.com #documentation"
138+ )
139+ . unwrap ( ) ;
140+ writeln ! (
141+ temp_file,
142+ "/docs/api/**/*.md @org/api-docs @victor api-docs@company.com #documentation #api"
143+ )
144+ . unwrap ( ) ;
145+ writeln ! (
146+ temp_file,
147+ "/config/**/*.toml @org/config-team @walter config@company.com #configuration"
148+ )
149+ . unwrap ( ) ;
150+ writeln ! (
151+ temp_file,
152+ "/config/**/*.json @org/config-team config@company.com #configuration #json"
153+ )
154+ . unwrap ( ) ;
155+ writeln ! ( temp_file) . unwrap ( ) ;
156+ writeln ! ( temp_file, "# Testing and quality" ) . unwrap ( ) ;
157+ writeln ! (
158+ temp_file,
159+ "/tests/**/*.rs @org/qa-team @xander @yara qa@company.com #testing #rust"
160+ )
161+ . unwrap ( ) ;
162+ writeln ! (
163+ temp_file,
164+ "/tests/**/*.js @org/qa-frontend qa-frontend@company.com #testing #javascript"
165+ )
166+ . unwrap ( ) ;
167+ writeln ! (
168+ temp_file,
169+ "/benchmarks/**/* @org/performance @zoe perf@company.com #performance #benchmarks"
170+ )
171+ . unwrap ( ) ;
172+ writeln ! ( temp_file) . unwrap ( ) ;
173+ writeln ! ( temp_file, "# Special files and patterns" ) . unwrap ( ) ;
174+ writeln ! (
175+ temp_file,
176+ "Cargo.toml @org/rust-maintainers rust@company.com #rust #dependencies"
177+ )
178+ . unwrap ( ) ;
179+ writeln ! (
180+ temp_file,
181+ "package.json @org/js-maintainers js@company.com #javascript #dependencies"
182+ )
183+ . unwrap ( ) ;
184+ writeln ! (
185+ temp_file,
186+ "go.mod @org/go-maintainers go@company.com #go #dependencies"
187+ )
188+ . unwrap ( ) ;
189+ writeln ! (
190+ temp_file,
191+ "requirements.txt @org/python-maintainers python@company.com #python #dependencies"
192+ )
193+ . unwrap ( ) ;
194+ writeln ! (
195+ temp_file,
196+ "Dockerfile* @org/docker-team docker@company.com #docker #containers"
197+ )
198+ . unwrap ( ) ;
199+ writeln ! (
200+ temp_file,
201+ "*.dockerfile @org/docker-team #docker #containers"
202+ )
203+ . unwrap ( ) ;
204+ writeln ! ( temp_file) . unwrap ( ) ;
205+ writeln ! ( temp_file, "# Root level important files" ) . unwrap ( ) ;
206+ writeln ! (
207+ temp_file,
208+ "README.md @org/maintainers @alice @bob maintainers@company.com #readme #documentation"
209+ )
210+ . unwrap ( ) ;
211+ writeln ! ( temp_file, "LICENSE @org/legal legal@company.com #legal" ) . unwrap ( ) ;
212+ writeln ! ( temp_file, "CODEOWNERS @org/maintainers #meta" ) . unwrap ( ) ;
213+ writeln ! ( temp_file, ".gitignore @org/maintainers #git #configuration" ) . unwrap ( ) ;
214+ temp_file. flush ( ) . unwrap ( ) ;
215+
216+ c. bench_function ( "parse_codeowners_complex" , |b| {
217+ b. iter ( || parse_codeowners ( black_box ( temp_file. path ( ) ) ) . unwrap ( ) )
218+ } ) ;
219+ }
220+
221+ // parse_line benchmarks (5 variations)
5222fn bench_parse_line_simple ( c : & mut Criterion ) {
6223 let source_path = Path :: new ( "/test/CODEOWNERS" ) ;
7224
@@ -16,5 +233,108 @@ fn bench_parse_line_simple(c: &mut Criterion) {
16233 } ) ;
17234}
18235
19- criterion_group ! ( benches, bench_parse_line_simple) ;
236+ fn bench_parse_line_multiple_owners ( c : & mut Criterion ) {
237+ let source_path = Path :: new ( "/test/CODEOWNERS" ) ;
238+
239+ c. bench_function ( "parse_line_multiple_owners" , |b| {
240+ b. iter ( || {
241+ parse_line (
242+ black_box ( "*.ts @frontend @org/ui-team user@example.com" ) ,
243+ black_box ( 1 ) ,
244+ black_box ( source_path) ,
245+ )
246+ } )
247+ } ) ;
248+ }
249+
250+ fn bench_parse_line_with_tags ( c : & mut Criterion ) {
251+ let source_path = Path :: new ( "/test/CODEOWNERS" ) ;
252+
253+ c. bench_function ( "parse_line_with_tags" , |b| {
254+ b. iter ( || {
255+ parse_line (
256+ black_box ( "/security/ @security-team #security #critical" ) ,
257+ black_box ( 1 ) ,
258+ black_box ( source_path) ,
259+ )
260+ } )
261+ } ) ;
262+ }
263+
264+ fn bench_parse_line_complex ( c : & mut Criterion ) {
265+ let source_path = Path :: new ( "/test/CODEOWNERS" ) ;
266+
267+ c. bench_function ( "parse_line_complex" , |b| {
268+ b. iter ( || {
269+ parse_line (
270+ black_box ( "/src/components/**/*.tsx @org/frontend @alice @bob user@example.com #ui #react #frontend # Complex component ownership" ) ,
271+ black_box ( 1 ) ,
272+ black_box ( source_path) ,
273+ )
274+ } )
275+ } ) ;
276+ }
277+
278+ fn bench_parse_line_comment ( c : & mut Criterion ) {
279+ let source_path = Path :: new ( "/test/CODEOWNERS" ) ;
280+
281+ c. bench_function ( "parse_line_comment" , |b| {
282+ b. iter ( || {
283+ parse_line (
284+ black_box ( "# This is just a comment line" ) ,
285+ black_box ( 1 ) ,
286+ black_box ( source_path) ,
287+ )
288+ } )
289+ } ) ;
290+ }
291+
292+ // parse_owner benchmarks (5 variations)
293+ fn bench_parse_owner_user ( c : & mut Criterion ) {
294+ c. bench_function ( "parse_owner_user" , |b| {
295+ b. iter ( || parse_owner ( black_box ( "@username" ) ) . unwrap ( ) )
296+ } ) ;
297+ }
298+
299+ fn bench_parse_owner_team ( c : & mut Criterion ) {
300+ c. bench_function ( "parse_owner_team" , |b| {
301+ b. iter ( || parse_owner ( black_box ( "@org/frontend-team" ) ) . unwrap ( ) )
302+ } ) ;
303+ }
304+
305+ fn bench_parse_owner_email ( c : & mut Criterion ) {
306+ c. bench_function ( "parse_owner_email" , |b| {
307+ b. iter ( || parse_owner ( black_box ( "user.name+tag@subdomain.example.com" ) ) . unwrap ( ) )
308+ } ) ;
309+ }
310+
311+ fn bench_parse_owner_unowned ( c : & mut Criterion ) {
312+ c. bench_function ( "parse_owner_unowned" , |b| {
313+ b. iter ( || parse_owner ( black_box ( "NOOWNER" ) ) . unwrap ( ) )
314+ } ) ;
315+ }
316+
317+ fn bench_parse_owner_unknown ( c : & mut Criterion ) {
318+ c. bench_function ( "parse_owner_unknown" , |b| {
319+ b. iter ( || parse_owner ( black_box ( "some-random-text-123" ) ) . unwrap ( ) )
320+ } ) ;
321+ }
322+
323+ criterion_group ! (
324+ benches,
325+ bench_parse_codeowners_small_file,
326+ bench_parse_codeowners_medium_file,
327+ bench_parse_codeowners_complex_file,
328+ bench_parse_line_simple,
329+ bench_parse_line_multiple_owners,
330+ bench_parse_line_with_tags,
331+ bench_parse_line_complex,
332+ bench_parse_line_comment,
333+ bench_parse_owner_user,
334+ bench_parse_owner_team,
335+ bench_parse_owner_email,
336+ bench_parse_owner_unowned,
337+ bench_parse_owner_unknown
338+ ) ;
20339criterion_main ! ( benches) ;
340+
0 commit comments