11use std:: collections:: HashMap ;
22
33use codecov_rs:: {
4- parsers:: pyreport:: { chunks , chunks_serde, report_json} ,
5- test_utils:: test_report:: { TestReport , TestReportBuilder } ,
4+ parsers:: pyreport:: { chunks_serde, report_json} ,
5+ test_utils:: test_report:: TestReportBuilder ,
66} ;
77use criterion:: { criterion_group, criterion_main, Criterion } ;
88use test_utils:: fixtures:: { read_fixture, FixtureFormat :: Pyreport , FixtureSize :: Large } ;
9- use winnow:: Parser as _;
109
1110criterion_group ! (
1211 benches,
@@ -55,24 +54,25 @@ fn parse_report_json(input: &[u8]) -> report_json::ParsedReportJson {
5554}
5655
5756fn simple_chunks ( c : & mut Criterion ) {
58- let chunks = & [
57+ let chunks: & [ & [ u8 ] ] = & [
5958 // Header and one chunk with an empty line
60- "{}\n <<<<< end_of_header >>>>>\n {}\n " ,
59+ b "{}\n <<<<< end_of_header >>>>>\n {}\n ",
6160 // No header, one chunk with a populated line and an empty line
62- "{}\n [1, null, [[0, 1]]]\n " ,
61+ b "{}\n [1, null, [[0, 1]]]\n ",
6362 // No header, two chunks, the second having just one empty line
64- "{}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n " ,
63+ b "{}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n ",
6564 // Header, two chunks, the second having multiple data lines and an empty line
66- "{}\n <<<<< end_of_header >>>>>\n {}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n [1, null, [[0, 1]]]\n [1, null, [[0, 1]]]\n " ,
65+ b "{}\n <<<<< end_of_header >>>>>\n {}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n [1, null, [[0, 1]]]\n [1, null, [[0, 1]]]\n ",
6766 ] ;
6867
6968 let files = HashMap :: from ( [ ( 0 , 0 ) , ( 1 , 1 ) , ( 2 , 2 ) ] ) ;
7069 let sessions = HashMap :: from ( [ ( 0 , 0 ) , ( 1 , 1 ) , ( 2 , 2 ) ] ) ;
7170
71+ let report_json = report_json:: ParsedReportJson { files, sessions } ;
7272 c. bench_function ( "simple_chunks" , |b| {
7373 b. iter ( || {
7474 for input in chunks {
75- parse_chunks_file ( input, files . clone ( ) , sessions . clone ( ) )
75+ parse_chunks_file_serde ( input, report_json . clone ( ) ) ;
7676 }
7777 } )
7878 } ) ;
@@ -87,7 +87,6 @@ fn complex_chunks(c: &mut Criterion) {
8787 "worker-c71ddfd4cb1753c7a540e5248c2beaa079fc3341-chunks.txt" ,
8888 )
8989 . unwrap ( ) ;
90- let chunks = std:: str:: from_utf8 ( & chunks) . unwrap ( ) ;
9190
9291 // parsing the chunks depends on having loaded the `report_json`
9392 let report = read_fixture (
@@ -96,79 +95,14 @@ fn complex_chunks(c: &mut Criterion) {
9695 "worker-c71ddfd4cb1753c7a540e5248c2beaa079fc3341-report_json.json" ,
9796 )
9897 . unwrap ( ) ;
99- let report_json:: ParsedReportJson { files , sessions } = parse_report_json ( & report) ;
98+ let report_json = parse_report_json ( & report) ;
10099
101100 c. bench_function ( "complex_chunks" , |b| {
102- b. iter ( || parse_chunks_file ( chunks, files . clone ( ) , sessions . clone ( ) ) )
101+ b. iter ( || parse_chunks_file_serde ( & chunks, report_json . clone ( ) ) )
103102 } ) ;
104103}
105104
106- fn parse_chunks_file ( input : & str , files : HashMap < usize , i64 > , sessions : HashMap < usize , i64 > ) {
105+ fn parse_chunks_file_serde ( input : & [ u8 ] , report_json : report_json :: ParsedReportJson ) {
107106 let report_builder = TestReportBuilder :: default ( ) ;
108-
109- let chunks_ctx = chunks:: ParseCtx :: new ( report_builder, files, sessions) ;
110- let mut chunks_stream = chunks:: ReportOutputStream :: < & str , TestReport , TestReportBuilder > {
111- input,
112- state : chunks_ctx,
113- } ;
114-
115- chunks:: parse_chunks_file
116- . parse_next ( & mut chunks_stream)
117- . unwrap ( ) ;
118- }
119-
120- #[ divan:: bench]
121- fn simple_chunks_serde ( ) {
122- let chunks: & [ & [ u8 ] ] = & [
123- // Header and one chunk with an empty line
124- b"{}\n <<<<< end_of_header >>>>>\n {}\n " ,
125- // No header, one chunk with a populated line and an empty line
126- b"{}\n [1, null, [[0, 1]]]\n " ,
127- // No header, two chunks, the second having just one empty line
128- b"{}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n " ,
129- // Header, two chunks, the second having multiple data lines and an empty line
130- b"{}\n <<<<< end_of_header >>>>>\n {}\n [1, null, [[0, 1]]]\n \n <<<<< end_of_chunk >>>>>\n {}\n [1, null, [[0, 1]]]\n [1, null, [[0, 1]]]\n " ,
131- ] ;
132-
133- let report_json = report_json:: ParsedReportJson {
134- files : Default :: default ( ) ,
135- sessions : Default :: default ( ) ,
136- } ;
137-
138- for input in chunks {
139- parse_chunks_file_serde ( input, & report_json) ;
140- }
141- }
142-
143- // this is currently <300 ms on my machine
144- #[ divan:: bench( sample_count = 10 ) ]
145- fn complex_chunks_serde ( bencher : Bencher ) {
146- // this is a ~96M `chunks` file
147- let chunks =
148- load_fixture ( "pyreport/large/worker-c71ddfd4cb1753c7a540e5248c2beaa079fc3341-chunks.txt" ) ;
149-
150- // parsing the chunks depends on having loaded the `report_json`
151- let report = load_fixture (
152- "pyreport/large/worker-c71ddfd4cb1753c7a540e5248c2beaa079fc3341-report_json.json" ,
153- ) ;
154- let report_json = parse_report_json ( & report) ;
155-
156- bencher. bench ( || parse_chunks_file_serde ( & chunks, & report_json) ) ;
157- }
158-
159- fn parse_chunks_file_serde ( input : & [ u8 ] , report_json : & report_json:: ParsedReportJson ) {
160- let mut report_builder = TestReportBuilder :: default ( ) ;
161- chunks_serde:: parse_chunks_file ( input, report_json, & mut report_builder) . unwrap ( ) ;
162- }
163-
164- #[ track_caller]
165- fn load_fixture ( path : & str ) -> Vec < u8 > {
166- let path = format ! ( "./fixtures/{path}" ) ;
167- let contents = std:: fs:: read ( path) . unwrap ( ) ;
168-
169- if contents. starts_with ( b"version https://git-lfs.github.com/spec/v1" ) {
170- panic ! ( "Fixture has not been pulled from Git LFS" ) ;
171- }
172-
173- contents
107+ chunks_serde:: parse_chunks_file ( input, report_json, report_builder) . unwrap ( ) ;
174108}
0 commit comments