1+ import { readFile } from "fs/promises" ;
2+ import * as constants from "../build/wasm/constants.js" ;
3+
4+ function http ( input ) {
5+ return input
6+ . trim ( )
7+ . replaceAll ( / ^ \s + / gm, "" )
8+ . replaceAll ( "\n" , "" )
9+ . replaceAll ( "\\r" , "\r" )
10+ . replaceAll ( "\\n" , "\n" ) ;
11+ }
12+
13+ function formatNumber ( num , precision ) {
14+ return num
15+ . toLocaleString ( "en-US" , {
16+ minimumFractionDigits : precision ,
17+ maximumFractionDigits : precision ,
18+ useGrouping : "always" ,
19+ } )
20+ . replaceAll ( "," , "_" ) ;
21+ }
22+
23+ /* eslint-disable @stylistic/max-len */
24+ const samples = {
25+ seanmonstar_httparse : http ( `
26+ GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\\r\\n
27+ Host: www.kittyhell.com\\r\\n
28+ User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\\r\\n
29+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\\r\\n
30+ Accept-Language: ja,en-us;q=0.7,en;q=0.3\\r\\n
31+ Accept-Encoding: gzip,deflate\\r\\n
32+ Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\\r\\n
33+ Keep-Alive: 115\\r\\n
34+ Connection: keep-alive\\r\\n
35+ Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\\r\\n\\r\\n
36+ ` ) ,
37+ nodejs_http_parser : http ( `
38+ POST /joyent/http-parser HTTP/1.1\\r\\n
39+ Host: github.com\\r\\n
40+ DNT: 1\\r\\n
41+ Accept-Encoding: gzip, deflate, sdch\\r\\n
42+ Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\\r\\n
43+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1)
44+ AppleWebKit/537.36 (KHTML, like Gecko)
45+ Chrome/39.0.2171.65 Safari/537.36\\r\\n
46+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,
47+ image/webp,*/*;q=0.8\\r\\n
48+ Referer: https://github.com/joyent/http-parser\\r\\n
49+ Connection: keep-alive\\r\\n
50+ Transfer-Encoding: chunked\\r\\n
51+ Cache-Control: max-age=0\\r\\n\\r\\nb\\r\\nhello world\\r\\n0\\r\\n\\r\\n
52+ ` )
53+ } ;
54+ /* eslint-enable @stylistic/max-len */
55+
56+ async function main ( ) {
57+ const mod = await WebAssembly . compile (
58+ await readFile ( new URL ( "../build/wasm/llhttp.wasm" , import . meta. url ) )
59+ ) ;
60+
61+ const { exports : llhttp } = await WebAssembly . instantiate ( mod , {
62+ env : {
63+ wasm_on_url ( ) {
64+ return 0 ;
65+ } ,
66+ wasm_on_status ( ) {
67+ return 0 ;
68+ } ,
69+ wasm_on_message_begin ( ) {
70+ return 0 ;
71+ } ,
72+ wasm_on_header_field ( ) {
73+ return 0 ;
74+ } ,
75+ wasm_on_header_value ( ) {
76+ return 0 ;
77+ } ,
78+ wasm_on_headers_complete ( ) {
79+ return 0 ;
80+ } ,
81+ wasm_on_body ( ) {
82+ return 0 ;
83+ } ,
84+ wasm_on_message_complete ( ) {
85+ return 0 ;
86+ } ,
87+ } ,
88+ } ) ;
89+
90+ for ( const [ name , payload ] of Object . entries ( samples ) ) {
91+ const len = payload . length ;
92+ const iterations = 2 ** 33 / len ;
93+ const total = iterations * len ;
94+
95+ const parser = llhttp . llhttp_alloc ( constants . TYPE . BOTH ) ;
96+ const ptr = llhttp . malloc ( len ) ;
97+ new Uint8Array ( llhttp . memory . buffer , ptr , len ) . set ( Buffer . from ( payload ) ) ;
98+
99+ const start = process . hrtime . bigint ( ) ;
100+ for ( let i = 0 ; i < iterations ; i ++ ) {
101+ llhttp . llhttp_execute ( parser , ptr , len ) ;
102+ }
103+
104+ llhttp . free ( ptr ) ;
105+ llhttp . llhttp_free ( ptr ) ;
106+
107+ const time = Number ( process . hrtime . bigint ( ) - start ) / 1e9 ;
108+ const bw = total / time ;
109+
110+ const label = name . padStart ( 21 , " " ) ;
111+ const samples = formatNumber ( iterations , 0 ) . padStart ( 12 ) ;
112+ const size = formatNumber ( total / ( 1024 * 1024 ) , 2 ) . padStart ( 8 ) ;
113+ const speed = formatNumber ( bw / ( 1024 * 1024 ) , 2 ) . padStart ( 10 ) ;
114+ const throughtput = formatNumber ( iterations / time , 2 ) . padStart ( 10 ) ;
115+ const duration = formatNumber ( time , 2 ) . padStart ( 6 ) ;
116+
117+ console . log (
118+ `${ label } | ${ samples } samples | ${ size } MB | ${ speed } MB/s | ${ throughtput } ops/sec | ${ duration } s`
119+ ) ;
120+ }
121+ }
122+
123+ main ( )
0 commit comments