44 * Two axes matter for CachedSource: cold vs warm (first call vs repeat call
55 * on the same instance), and the cache-data round-trip that lets webpack
66 * store cached state to disk via getCachedData() / re-hydrate.
7+ *
8+ * Fixture lifetime policy:
9+ * - Heavy fixtures (`warmed`, `warmedConcat`, `sink`) live inside
10+ * beforeAll/afterAll hooks so they are GC'd between tasks. This keeps
11+ * the V8 heap layout independent of how many tasks the file exports —
12+ * adding a new task does not perturb pre-existing tasks' measurements.
13+ * - Light fixtures (fixtureCode, fixtureMap) stay at module scope; they
14+ * are immutable and cheap to retain.
715 */
816
917import { createHash } from "crypto" ;
1018import sources from "../../../lib/index.js" ;
1119import { fixtureCode , fixtureMap , noop } from "../../fixtures.mjs" ;
1220
13- /**
14- * Pre-sized sink used by allocation-heavy tasks to retain the constructed
15- * instances past the loop so V8 cannot dead-code-eliminate them and so
16- * memory pressure is predictable between samples. Overwriting existing
17- * slots (rather than push/length reset) keeps the sink's hidden class
18- * stable and avoids resize allocations during measurement.
19- */
2021const CONSTRUCT_BATCH = 100 ;
21- const sink = Array . from ( { length : CONSTRUCT_BATCH } ) ;
2222
2323/**
24- * A CachedSource with all the common caches already populated. Reused
25- * across tasks that explicitly measure the warm path.
24+ * @returns {CachedSource } warmed CachedSource with all common caches populated
2625 */
27- const warmed = ( ( ) => {
26+ function makeWarmed ( ) {
2827 const cached = new sources . CachedSource (
2928 new sources . SourceMapSource ( fixtureCode , "fixture.js" , fixtureMap ) ,
3029 ) ;
@@ -34,36 +33,146 @@ const warmed = (() => {
3433 cached . buffer ( ) ;
3534 cached . size ( ) ;
3635 return cached ;
37- } ) ( ) ;
36+ }
37+
38+ /**
39+ * @returns {CachedSource } CachedSource wrapping a ConcatSource of 10 RawSources,
40+ * with buffers() already populated
41+ */
42+ function makeWarmedConcat ( ) {
43+ const parts = [ ] ;
44+ for ( let i = 0 ; i < 10 ; i ++ ) parts . push ( new sources . RawSource ( fixtureCode ) ) ;
45+ const cached = new sources . CachedSource ( new sources . ConcatSource ( ...parts ) ) ;
46+ cached . buffers ( ) ;
47+ return cached ;
48+ }
3849
3950/**
4051 * @param {import("tinybench").Bench } bench bench
4152 */
4253export default function register ( bench ) {
43- bench . add ( "cached-source: new CachedSource()" , ( ) => {
44- for ( let i = 0 ; i < CONSTRUCT_BATCH ; i ++ ) {
45- sink [ i ] = new sources . CachedSource ( new sources . RawSource ( fixtureCode ) ) ;
46- }
47- } ) ;
54+ /** @type {unknown[] | undefined } */
55+ let sink ;
56+ bench . add (
57+ "cached-source: new CachedSource()" ,
58+ ( ) => {
59+ const arr = /** @type {unknown[] } */ ( sink ) ;
60+ for ( let i = 0 ; i < CONSTRUCT_BATCH ; i ++ ) {
61+ arr [ i ] = new sources . CachedSource ( new sources . RawSource ( fixtureCode ) ) ;
62+ }
63+ } ,
64+ {
65+ beforeAll ( ) {
66+ sink = Array . from ( { length : CONSTRUCT_BATCH } ) ;
67+ } ,
68+ afterAll ( ) {
69+ sink = undefined ;
70+ } ,
71+ } ,
72+ ) ;
4873
4974 bench . add ( "cached-source: source() (cold)" , ( ) => {
5075 for ( let i = 0 ; i < 50 ; i ++ ) {
5176 new sources . CachedSource ( new sources . RawSource ( fixtureCode ) ) . source ( ) ;
5277 }
5378 } ) ;
5479
55- bench . add ( "cached-source: source() (cached)" , ( ) => {
56- for ( let i = 0 ; i < 500 ; i ++ ) warmed . source ( ) ;
57- } ) ;
80+ /** @type {CachedSource | undefined } */
81+ let warmed ;
82+ const warmedHooks = {
83+ beforeAll ( ) {
84+ warmed = makeWarmed ( ) ;
85+ } ,
86+ afterAll ( ) {
87+ warmed = undefined ;
88+ } ,
89+ } ;
90+
91+ bench . add (
92+ "cached-source: source() (cached)" ,
93+ ( ) => {
94+ const cs = /** @type {CachedSource } */ ( warmed ) ;
95+ for ( let i = 0 ; i < 500 ; i ++ ) cs . source ( ) ;
96+ } ,
97+ warmedHooks ,
98+ ) ;
5899
59- bench . add ( "cached-source: buffer() (cached)" , ( ) => {
60- for ( let i = 0 ; i < 500 ; i ++ ) warmed . buffer ( ) ;
100+ bench . add (
101+ "cached-source: buffer() (cached)" ,
102+ ( ) => {
103+ const cs = /** @type {CachedSource } */ ( warmed ) ;
104+ for ( let i = 0 ; i < 500 ; i ++ ) cs . buffer ( ) ;
105+ } ,
106+ warmedHooks ,
107+ ) ;
108+
109+ bench . add (
110+ "cached-source: buffers() (cached)" ,
111+ ( ) => {
112+ const cs = /** @type {CachedSource } */ ( warmed ) ;
113+ for ( let i = 0 ; i < 500 ; i ++ ) cs . buffers ( ) ;
114+ } ,
115+ warmedHooks ,
116+ ) ;
117+
118+ bench . add ( "cached-source: buffer() (cold, wraps ConcatSource x10)" , ( ) => {
119+ for ( let i = 0 ; i < 10 ; i ++ ) {
120+ const parts = [ ] ;
121+ for ( let j = 0 ; j < 10 ; j ++ ) {
122+ parts . push ( new sources . RawSource ( fixtureCode ) ) ;
123+ }
124+ new sources . CachedSource ( new sources . ConcatSource ( ...parts ) ) . buffer ( ) ;
125+ }
61126 } ) ;
62127
63- bench . add ( "cached-source: size() (cached)" , ( ) => {
64- for ( let i = 0 ; i < 500 ; i ++ ) warmed . size ( ) ;
128+ bench . add ( "cached-source: buffers() (cold, wraps ConcatSource x10)" , ( ) => {
129+ for ( let i = 0 ; i < 10 ; i ++ ) {
130+ const parts = [ ] ;
131+ for ( let j = 0 ; j < 10 ; j ++ ) {
132+ parts . push ( new sources . RawSource ( fixtureCode ) ) ;
133+ }
134+ new sources . CachedSource ( new sources . ConcatSource ( ...parts ) ) . buffers ( ) ;
135+ }
65136 } ) ;
66137
138+ /** @type {CachedSource | undefined } */
139+ let warmedConcat ;
140+ const warmedConcatHooks = {
141+ beforeAll ( ) {
142+ warmedConcat = makeWarmedConcat ( ) ;
143+ } ,
144+ afterAll ( ) {
145+ warmedConcat = undefined ;
146+ } ,
147+ } ;
148+
149+ bench . add (
150+ "cached-source: buffer() (warm, wraps ConcatSource x10)" ,
151+ ( ) => {
152+ const cs = /** @type {CachedSource } */ ( warmedConcat ) ;
153+ for ( let i = 0 ; i < 500 ; i ++ ) cs . buffer ( ) ;
154+ } ,
155+ warmedConcatHooks ,
156+ ) ;
157+
158+ bench . add (
159+ "cached-source: buffers() (warm, wraps ConcatSource x10)" ,
160+ ( ) => {
161+ const cs = /** @type {CachedSource } */ ( warmedConcat ) ;
162+ for ( let i = 0 ; i < 500 ; i ++ ) cs . buffers ( ) ;
163+ } ,
164+ warmedConcatHooks ,
165+ ) ;
166+
167+ bench . add (
168+ "cached-source: size() (cached)" ,
169+ ( ) => {
170+ const cs = /** @type {CachedSource } */ ( warmed ) ;
171+ for ( let i = 0 ; i < 500 ; i ++ ) cs . size ( ) ;
172+ } ,
173+ warmedHooks ,
174+ ) ;
175+
67176 bench . add ( "cached-source: map() (cold SourceMapSource)" , ( ) => {
68177 for ( let i = 0 ; i < 10 ; i ++ ) {
69178 new sources . CachedSource (
@@ -72,9 +181,14 @@ export default function register(bench) {
72181 }
73182 } ) ;
74183
75- bench . add ( "cached-source: map() (cached)" , ( ) => {
76- for ( let i = 0 ; i < 500 ; i ++ ) warmed . map ( { } ) ;
77- } ) ;
184+ bench . add (
185+ "cached-source: map() (cached)" ,
186+ ( ) => {
187+ const cs = /** @type {CachedSource } */ ( warmed ) ;
188+ for ( let i = 0 ; i < 500 ; i ++ ) cs . map ( { } ) ;
189+ } ,
190+ warmedHooks ,
191+ ) ;
78192
79193 bench . add ( "cached-source: sourceAndMap() (cold)" , ( ) => {
80194 for ( let i = 0 ; i < 10 ; i ++ ) {
@@ -84,9 +198,14 @@ export default function register(bench) {
84198 }
85199 } ) ;
86200
87- bench . add ( "cached-source: sourceAndMap() (cached)" , ( ) => {
88- for ( let i = 0 ; i < 500 ; i ++ ) warmed . sourceAndMap ( { } ) ;
89- } ) ;
201+ bench . add (
202+ "cached-source: sourceAndMap() (cached)" ,
203+ ( ) => {
204+ const cs = /** @type {CachedSource } */ ( warmed ) ;
205+ for ( let i = 0 ; i < 500 ; i ++ ) cs . sourceAndMap ( { } ) ;
206+ } ,
207+ warmedHooks ,
208+ ) ;
90209
91210 bench . add ( "cached-source: streamChunks() (cold)" , ( ) => {
92211 for ( let i = 0 ; i < 5 ; i ++ ) {
@@ -96,11 +215,16 @@ export default function register(bench) {
96215 }
97216 } ) ;
98217
99- bench . add ( "cached-source: streamChunks() (warm)" , ( ) => {
100- for ( let i = 0 ; i < 5 ; i ++ ) {
101- warmed . streamChunks ( { } , noop , noop , noop ) ;
102- }
103- } ) ;
218+ bench . add (
219+ "cached-source: streamChunks() (warm)" ,
220+ ( ) => {
221+ const cs = /** @type {CachedSource } */ ( warmed ) ;
222+ for ( let i = 0 ; i < 5 ; i ++ ) {
223+ cs . streamChunks ( { } , noop , noop , noop ) ;
224+ }
225+ } ,
226+ warmedHooks ,
227+ ) ;
104228
105229 bench . add ( "cached-source: originalLazy()" , ( ) => {
106230 const lazy = new sources . CachedSource (
@@ -124,7 +248,12 @@ export default function register(bench) {
124248 }
125249 } ) ;
126250
127- bench . add ( "cached-source: updateHash() (warm)" , ( ) => {
128- for ( let i = 0 ; i < 50 ; i ++ ) warmed . updateHash ( createHash ( "sha256" ) ) ;
129- } ) ;
251+ bench . add (
252+ "cached-source: updateHash() (warm)" ,
253+ ( ) => {
254+ const cs = /** @type {CachedSource } */ ( warmed ) ;
255+ for ( let i = 0 ; i < 50 ; i ++ ) cs . updateHash ( createHash ( "sha256" ) ) ;
256+ } ,
257+ warmedHooks ,
258+ ) ;
130259}
0 commit comments