@@ -70,17 +70,31 @@ export function validatePkgJson(packageJson, options = {}) {
70
70
}
71
71
72
72
/**
73
- * Measures the performance of a function.
74
- * @param {string } label - The label for the performance measurement.
75
- * @param {Function } fn - The function to measure.
76
- * @returns {Promise<number> } - The duration of the function execution in milliseconds.
73
+ * Marks the start and end of a function execution for performance measurement.
74
+ * Uses the Performance API to create marks and measure the duration.
75
+ * @function
76
+ * @template {() => Promise<any>} F
77
+ * @param {string } label
78
+ * @param {() => ReturnType<F> } fn
79
+ * @returns {Promise<ReturnType<F>> }
80
+ */
81
+ export async function markFn ( label , fn ) {
82
+ const startMark = `${ label } -start` ;
83
+ const endMark = `${ label } -end` ;
84
+ performance . mark ( startMark ) ;
85
+ const result = await fn ( ) ;
86
+ performance . mark ( endMark ) ;
87
+ performance . measure ( label , startMark , endMark ) ;
88
+ return result ;
89
+ }
90
+
91
+ /**
92
+ * @param {string } label
77
93
*/
78
- export async function measurePerf ( label , fn ) {
79
- performance . mark ( `${ label } -start` ) ;
80
- await Promise . resolve ( fn ( ) ) ;
81
- performance . mark ( `${ label } -end` ) ;
82
- const measurement = performance . measure ( label , `${ label } -start` , `${ label } -end` ) ;
83
- return measurement . duration ;
94
+ export function measureFn ( label ) {
95
+ const startMark = `${ label } -start` ;
96
+ const endMark = `${ label } -end` ;
97
+ return performance . measure ( label , startMark , endMark ) ;
84
98
}
85
99
86
100
export const BASE_IGNORES = [
@@ -96,35 +110,40 @@ export const BASE_IGNORES = [
96
110
] ;
97
111
98
112
/**
99
- * A utility to wrap a function in a worker pool.
113
+ * A utility to map a function over an array of items in a worker pool.
100
114
*
101
115
* This function will create a pool of workers and distribute the items to be processed among them.
102
116
* Each worker will process items sequentially, but multiple workers will run in parallel.
117
+ *
103
118
* @function
104
119
* @template T
105
- * @param {(item: T) => Promise<void> } fn
106
- * @param {Object } options
107
- * @param {T[] } options.items
108
- * @param {number } [options.defaultConcurrency=50]
109
- * @param {'all' | 'allSettled' } [options.promiseMethod='all']
110
- * @returns {Promise<void> }
120
+ * @template R
121
+ * @param {T[] } items
122
+ * @param {(item: T) => Promise<R> } mapper
123
+ * @param {number } concurrency
124
+ * @returns {Promise<(R|Error)[]> }
111
125
*/
112
- export async function wrapInWorker ( fn , options ) {
113
- const { defaultConcurrency = 50 , items = [ ] , promiseMethod = 'all' } = options ?? { } ;
114
- if ( items . length === 0 ) {
115
- return ;
126
+ export async function mapConcurrently ( items , mapper , concurrency ) {
127
+ if ( ! items . length ) {
128
+ return Promise . resolve ( [ ] ) ; // nothing to do
116
129
}
117
- const itemIterator = items [ Symbol . iterator ] ( ) ;
118
- const concurrency = Math . min ( defaultConcurrency , items . length ) ;
130
+ const itemIterator = items . entries ( ) ;
131
+ const count = Math . min ( concurrency , items . length ) ;
119
132
const workers = [ ] ;
120
- for ( let i = 0 ; i < concurrency ; i += 1 ) {
133
+ /**
134
+ * @type {(R|Error)[] }
135
+ */
136
+ const results = new Array ( items . length ) ;
137
+ for ( let i = 0 ; i < count ; i += 1 ) {
121
138
const worker = Promise . resolve ( ) . then ( async ( ) => {
122
- for ( const item of itemIterator ) {
139
+ for ( const [ index , item ] of itemIterator ) {
123
140
// eslint-disable-next-line no-await-in-loop
124
- await fn ( item ) ;
141
+ const res = await mapper ( item ) ;
142
+ results [ index ] = res ;
125
143
}
126
144
} ) ;
127
145
workers . push ( worker ) ;
128
146
}
129
- await ( promiseMethod === 'all' ? Promise . all ( workers ) : Promise . allSettled ( workers ) ) ;
147
+ await Promise . all ( workers ) ;
148
+ return results ;
130
149
}
0 commit comments