@parcel/workers 2.0.0-nightly.97 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
package/lib/WorkerFarm.js CHANGED
@@ -11,15 +11,55 @@ Object.defineProperty(exports, "Handle", {
11
11
  });
12
12
  exports.default = void 0;
13
13
 
14
- var _assert = _interopRequireDefault(require("assert"));
14
+ function _assert() {
15
+ const data = _interopRequireDefault(require("assert"));
15
16
 
16
- var _nullthrows = _interopRequireDefault(require("nullthrows"));
17
+ _assert = function () {
18
+ return data;
19
+ };
17
20
 
18
- var _events = _interopRequireDefault(require("events"));
21
+ return data;
22
+ }
23
+
24
+ function _nullthrows() {
25
+ const data = _interopRequireDefault(require("nullthrows"));
26
+
27
+ _nullthrows = function () {
28
+ return data;
29
+ };
30
+
31
+ return data;
32
+ }
33
+
34
+ function _events() {
35
+ const data = _interopRequireDefault(require("events"));
36
+
37
+ _events = function () {
38
+ return data;
39
+ };
40
+
41
+ return data;
42
+ }
43
+
44
+ function _core() {
45
+ const data = require("@parcel/core");
46
+
47
+ _core = function () {
48
+ return data;
49
+ };
50
+
51
+ return data;
52
+ }
53
+
54
+ function _diagnostic() {
55
+ const data = _interopRequireWildcard(require("@parcel/diagnostic"));
19
56
 
20
- var _core = require("@parcel/core");
57
+ _diagnostic = function () {
58
+ return data;
59
+ };
21
60
 
22
- var _diagnostic = _interopRequireWildcard(require("@parcel/diagnostic"));
61
+ return data;
62
+ }
23
63
 
24
64
  var _Worker = _interopRequireDefault(require("./Worker"));
25
65
 
@@ -35,83 +75,58 @@ var _Profiler = _interopRequireDefault(require("./Profiler"));
35
75
 
36
76
  var _Trace = _interopRequireDefault(require("./Trace"));
37
77
 
38
- var _fs = _interopRequireDefault(require("fs"));
78
+ function _fs() {
79
+ const data = _interopRequireDefault(require("fs"));
39
80
 
40
- var _logger = _interopRequireDefault(require("@parcel/logger"));
81
+ _fs = function () {
82
+ return data;
83
+ };
41
84
 
42
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
85
+ return data;
86
+ }
43
87
 
44
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
88
+ function _logger() {
89
+ const data = _interopRequireDefault(require("@parcel/logger"));
45
90
 
46
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
91
+ _logger = function () {
92
+ return data;
93
+ };
94
+
95
+ return data;
96
+ }
47
97
 
48
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
98
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
49
99
 
50
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
100
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
51
101
 
52
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
102
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
53
103
 
54
- let profileId = 1;
55
104
  let referenceId = 1;
56
105
 
57
106
  /**
58
107
  * workerPath should always be defined inside farmOptions
59
108
  */
60
- class WorkerFarm extends _events.default {
109
+ class WorkerFarm extends _events().default {
110
+ callQueue = [];
111
+ ending = false;
112
+ warmWorkers = 0;
113
+ workers = new Map();
114
+ handles = new Map();
115
+ sharedReferences = new Map();
116
+ sharedReferencesByValue = new Map();
117
+
61
118
  constructor(farmOptions = {}) {
62
119
  super();
63
-
64
- _defineProperty(this, "callQueue", []);
65
-
66
- _defineProperty(this, "ending", false);
67
-
68
- _defineProperty(this, "localWorker", void 0);
69
-
70
- _defineProperty(this, "options", void 0);
71
-
72
- _defineProperty(this, "run", void 0);
73
-
74
- _defineProperty(this, "warmWorkers", 0);
75
-
76
- _defineProperty(this, "workers", new Map());
77
-
78
- _defineProperty(this, "handles", new Map());
79
-
80
- _defineProperty(this, "sharedReferences", new Map());
81
-
82
- _defineProperty(this, "sharedReferencesByValue", new Map());
83
-
84
- _defineProperty(this, "profiler", void 0);
85
-
86
- _defineProperty(this, "workerApi", {
87
- callMaster: async (request, awaitResponse = true) => {
88
- // $FlowFixMe
89
- let result = await this.processRequest(_objectSpread({}, request, {
90
- awaitResponse
91
- }));
92
- return (0, _core.deserialize)((0, _core.serialize)(result));
93
- },
94
- createReverseHandle: fn => this.createReverseHandle(fn),
95
- callChild: (childId, request) => new Promise((resolve, reject) => {
96
- (0, _nullthrows.default)(this.workers.get(childId)).call(_objectSpread({}, request, {
97
- resolve,
98
- reject,
99
- retries: 0
100
- }));
101
- }),
102
- getSharedReference: ref => this.sharedReferences.get(ref),
103
- resolveSharedReference: value => this.sharedReferencesByValue.get(value)
104
- });
105
-
106
- this.options = _objectSpread({
120
+ this.options = {
107
121
  maxConcurrentWorkers: WorkerFarm.getNumWorkers(),
108
122
  maxConcurrentCallsPerWorker: WorkerFarm.getConcurrentCallsPerWorker(),
109
123
  forcedKillTime: 500,
110
124
  warmWorkers: false,
111
125
  useLocalWorker: true,
112
126
  // TODO: setting this to false makes some tests fail, figure out why
113
- backend: (0, _backend.detectBackend)()
114
- }, farmOptions);
127
+ backend: (0, _backend.detectBackend)(),
128
+ ...farmOptions
129
+ };
115
130
 
116
131
  if (!this.options.workerPath) {
117
132
  throw new Error('Please provide a worker path!');
@@ -119,10 +134,35 @@ class WorkerFarm extends _events.default {
119
134
 
120
135
 
121
136
  this.localWorker = require(this.options.workerPath);
137
+ this.localWorkerInit = this.localWorker.childInit != null ? this.localWorker.childInit() : null;
122
138
  this.run = this.createHandle('run');
123
139
  this.startMaxWorkers();
124
140
  }
125
141
 
142
+ workerApi = {
143
+ callMaster: async (request, awaitResponse = true) => {
144
+ // $FlowFixMe
145
+ let result = await this.processRequest({ ...request,
146
+ awaitResponse
147
+ });
148
+ return (0, _core().deserialize)((0, _core().serialize)(result));
149
+ },
150
+ createReverseHandle: fn => this.createReverseHandle(fn),
151
+ callChild: (childId, request) => new Promise((resolve, reject) => {
152
+ (0, _nullthrows().default)(this.workers.get(childId)).call({ ...request,
153
+ resolve,
154
+ reject,
155
+ retries: 0
156
+ });
157
+ }),
158
+ runHandle: (handle, args) => this.workerApi.callChild((0, _nullthrows().default)(handle.childId), {
159
+ handle: handle.id,
160
+ args
161
+ }),
162
+ getSharedReference: ref => this.sharedReferences.get(ref),
163
+ resolveSharedReference: value => this.sharedReferencesByValue.get(value)
164
+ };
165
+
126
166
  warmupWorker(method, args) {
127
167
  // Workers are already stopping
128
168
  if (this.ending) {
@@ -150,7 +190,7 @@ class WorkerFarm extends _events.default {
150
190
  }
151
191
 
152
192
  createHandle(method) {
153
- return (...args) => {
193
+ return async (...args) => {
154
194
  // Child process workers are slow to start (~600ms).
155
195
  // While we're waiting, just run on the main thread.
156
196
  // This significantly speeds up startup time.
@@ -161,7 +201,13 @@ class WorkerFarm extends _events.default {
161
201
  this.warmupWorker(method, args);
162
202
  }
163
203
 
164
- let processedArgs = (0, _core.restoreDeserializedObject)((0, _core.prepareForSerialization)([...args, false]));
204
+ let processedArgs = (0, _core().restoreDeserializedObject)((0, _core().prepareForSerialization)([...args, false]));
205
+
206
+ if (this.localWorkerInit != null) {
207
+ await this.localWorkerInit;
208
+ this.localWorkerInit = null;
209
+ }
210
+
165
211
  return this.localWorker[method](this.workerApi, ...processedArgs);
166
212
  }
167
213
  };
@@ -171,6 +217,8 @@ class WorkerFarm extends _events.default {
171
217
  // Handle ipc errors
172
218
  if (error.code === 'ERR_IPC_CHANNEL_CLOSED') {
173
219
  return this.stopWorker(worker);
220
+ } else {
221
+ _logger().default.error(error, '@parcel/workers');
174
222
  }
175
223
  }
176
224
 
@@ -178,9 +226,10 @@ class WorkerFarm extends _events.default {
178
226
  let worker = new _Worker.default({
179
227
  forcedKillTime: this.options.forcedKillTime,
180
228
  backend: this.options.backend,
181
- patchConsole: this.options.patchConsole
229
+ shouldPatchConsole: this.options.shouldPatchConsole,
230
+ sharedReferences: this.sharedReferences
182
231
  });
183
- worker.fork((0, _nullthrows.default)(this.options.workerPath));
232
+ worker.fork((0, _nullthrows().default)(this.options.workerPath));
184
233
  worker.on('request', data => this.processRequest(data, worker));
185
234
  worker.on('ready', () => this.processQueue());
186
235
  worker.on('response', () => this.processQueue());
@@ -215,7 +264,9 @@ class WorkerFarm extends _events.default {
215
264
  this.startChild();
216
265
  }
217
266
 
218
- for (let worker of this.workers.values()) {
267
+ let workers = [...this.workers.values()].sort((a, b) => a.calls.size - b.calls.size);
268
+
269
+ for (let worker of workers) {
219
270
  if (!this.callQueue.length) {
220
271
  break;
221
272
  }
@@ -242,7 +293,9 @@ class WorkerFarm extends _events.default {
242
293
  let mod;
243
294
 
244
295
  if (handleId != null) {
245
- mod = (0, _nullthrows.default)(this.handles.get(handleId)).fn;
296
+ var _this$handles$get;
297
+
298
+ mod = (0, _nullthrows().default)((_this$handles$get = this.handles.get(handleId)) === null || _this$handles$get === void 0 ? void 0 : _this$handles$get.fn);
246
299
  } else if (location) {
247
300
  // $FlowFixMe this must be dynamic
248
301
  mod = require(location);
@@ -261,27 +314,26 @@ class WorkerFarm extends _events.default {
261
314
  idx,
262
315
  type: 'response',
263
316
  contentType: 'error',
264
- content: (0, _diagnostic.anyToDiagnostic)(e)
317
+ content: (0, _diagnostic().anyToDiagnostic)(e)
265
318
  });
266
319
 
267
320
  let result;
268
321
 
269
322
  if (method == null) {
270
323
  try {
271
- result = responseFromContent((await mod(...args)));
324
+ result = responseFromContent(await mod(...args));
272
325
  } catch (e) {
273
326
  result = errorResponseFromError(e);
274
327
  }
275
328
  } else {
276
329
  // ESModule default interop
277
- // $FlowFixMe
278
330
  if (mod.__esModule && !mod[method] && mod.default) {
279
331
  mod = mod.default;
280
332
  }
281
333
 
282
334
  try {
283
335
  // $FlowFixMe
284
- result = responseFromContent((await mod[method](...args)));
336
+ result = responseFromContent(await mod[method](...args));
285
337
  } catch (e) {
286
338
  result = errorResponseFromError(e);
287
339
  }
@@ -292,7 +344,7 @@ class WorkerFarm extends _events.default {
292
344
  worker.send(result);
293
345
  } else {
294
346
  if (result.contentType === 'error') {
295
- throw new _diagnostic.default({
347
+ throw new (_diagnostic().default)({
296
348
  diagnostic: result.content
297
349
  });
298
350
  }
@@ -321,6 +373,7 @@ class WorkerFarm extends _events.default {
321
373
 
322
374
  async end() {
323
375
  this.ending = true;
376
+ await Promise.all(Array.from(this.workers.values()).map(worker => this.stopWorker(worker)));
324
377
 
325
378
  for (let handle of this.handles.values()) {
326
379
  handle.dispose();
@@ -329,7 +382,6 @@ class WorkerFarm extends _events.default {
329
382
  this.handles = new Map();
330
383
  this.sharedReferences = new Map();
331
384
  this.sharedReferencesByValue = new Map();
332
- await Promise.all(Array.from(this.workers.values()).map(worker => this.stopWorker(worker)));
333
385
  this.ending = false;
334
386
  }
335
387
 
@@ -350,29 +402,25 @@ class WorkerFarm extends _events.default {
350
402
 
351
403
  createReverseHandle(fn) {
352
404
  let handle = new _Handle.default({
353
- fn,
354
- workerApi: this.workerApi
405
+ fn
355
406
  });
356
407
  this.handles.set(handle.id, handle);
357
408
  return handle;
358
409
  }
359
410
 
360
- async createSharedReference(value) {
411
+ async createSharedReference(value, // An optional, pre-serialized representation of the value to be used
412
+ // in its place.
413
+ buffer) {
361
414
  let ref = referenceId++;
362
415
  this.sharedReferences.set(ref, value);
363
416
  this.sharedReferencesByValue.set(value, ref);
417
+ let toSend = buffer ? buffer.buffer : value;
364
418
  let promises = [];
365
419
 
366
420
  for (let worker of this.workers.values()) {
367
- promises.push(new Promise((resolve, reject) => {
368
- worker.call({
369
- method: 'createSharedReference',
370
- args: [ref, value],
371
- resolve,
372
- reject,
373
- retries: 0
374
- });
375
- }));
421
+ if (worker.ready) {
422
+ promises.push(worker.sendSharedReference(ref, toSend));
423
+ }
376
424
  }
377
425
 
378
426
  await Promise.all(promises);
@@ -390,6 +438,7 @@ class WorkerFarm extends _events.default {
390
438
  args: [ref],
391
439
  resolve,
392
440
  reject,
441
+ skipReadyCheck: true,
393
442
  retries: 0
394
443
  });
395
444
  }));
@@ -410,7 +459,8 @@ class WorkerFarm extends _events.default {
410
459
  args: [],
411
460
  resolve,
412
461
  reject,
413
- retries: 0
462
+ retries: 0,
463
+ skipReadyCheck: true
414
464
  });
415
465
  }));
416
466
  }
@@ -436,15 +486,16 @@ class WorkerFarm extends _events.default {
436
486
  args: [],
437
487
  resolve,
438
488
  reject,
439
- retries: 0
489
+ retries: 0,
490
+ skipReadyCheck: true
440
491
  });
441
492
  }));
442
493
  }
443
494
 
444
495
  var profiles = await Promise.all(promises);
445
496
  let trace = new _Trace.default();
446
- let filename = `profile-${profileId++}.trace`;
447
- let stream = trace.pipe(_fs.default.createWriteStream(filename));
497
+ let filename = `profile-${getTimeId()}.trace`;
498
+ let stream = trace.pipe(_fs().default.createWriteStream(filename));
448
499
 
449
500
  for (let profile of profiles) {
450
501
  trace.addCPUProfile(names.shift(), profile);
@@ -455,14 +506,60 @@ class WorkerFarm extends _events.default {
455
506
  stream.once('finish', resolve);
456
507
  });
457
508
 
458
- _logger.default.info({
509
+ _logger().default.info({
459
510
  origin: '@parcel/workers',
460
- message: `Wrote profile to ${filename}`
511
+ message: (0, _diagnostic().md)`Wrote profile to ${filename}`
461
512
  });
462
513
  }
463
514
 
515
+ async callAllWorkers(method, args) {
516
+ let promises = [];
517
+
518
+ for (let worker of this.workers.values()) {
519
+ promises.push(new Promise((resolve, reject) => {
520
+ worker.call({
521
+ method,
522
+ args,
523
+ resolve,
524
+ reject,
525
+ retries: 0
526
+ });
527
+ }));
528
+ }
529
+
530
+ promises.push(this.localWorker[method](this.workerApi, ...args));
531
+ await Promise.all(promises);
532
+ }
533
+
534
+ async takeHeapSnapshot() {
535
+ let snapshotId = getTimeId();
536
+
537
+ try {
538
+ let snapshotPaths = await Promise.all([...this.workers.values()].map(worker => new Promise((resolve, reject) => {
539
+ worker.call({
540
+ method: 'takeHeapSnapshot',
541
+ args: [snapshotId],
542
+ resolve,
543
+ reject,
544
+ retries: 0,
545
+ skipReadyCheck: true
546
+ });
547
+ })));
548
+
549
+ _logger().default.info({
550
+ origin: '@parcel/workers',
551
+ message: (0, _diagnostic().md)`Wrote heap snapshots to the following paths:\n${snapshotPaths.join('\n')}`
552
+ });
553
+ } catch {
554
+ _logger().default.error({
555
+ origin: '@parcel/workers',
556
+ message: 'Unable to take heap snapshots. Note: requires Node 11.13.0+'
557
+ });
558
+ }
559
+ }
560
+
464
561
  static getNumWorkers() {
465
- return process.env.PARCEL_WORKERS ? parseInt(process.env.PARCEL_WORKERS, 10) : (0, _cpuCount.default)();
562
+ return process.env.PARCEL_WORKERS ? parseInt(process.env.PARCEL_WORKERS, 10) : Math.ceil((0, _cpuCount.default)() / 2);
466
563
  }
467
564
 
468
565
  static isWorker() {
@@ -470,14 +567,19 @@ class WorkerFarm extends _events.default {
470
567
  }
471
568
 
472
569
  static getWorkerApi() {
473
- (0, _assert.default)(_childState.child != null, 'WorkerFarm.getWorkerApi can only be called within workers');
570
+ (0, _assert().default)(_childState.child != null, 'WorkerFarm.getWorkerApi can only be called within workers');
474
571
  return _childState.child.workerApi;
475
572
  }
476
573
 
477
574
  static getConcurrentCallsPerWorker() {
478
- return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 5;
575
+ return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 30;
479
576
  }
480
577
 
481
578
  }
482
579
 
483
- exports.default = WorkerFarm;
580
+ exports.default = WorkerFarm;
581
+
582
+ function getTimeId() {
583
+ let now = new Date();
584
+ return String(now.getFullYear()) + String(now.getMonth() + 1).padStart(2, '0') + String(now.getDate()).padStart(2, '0') + '-' + String(now.getHours()).padStart(2, '0') + String(now.getMinutes()).padStart(2, '0') + String(now.getSeconds()).padStart(2, '0');
585
+ }
package/lib/backend.js CHANGED
@@ -7,6 +7,12 @@ exports.detectBackend = detectBackend;
7
7
  exports.getWorkerBackend = getWorkerBackend;
8
8
 
9
9
  function detectBackend() {
10
+ switch (process.env.PARCEL_WORKER_BACKEND) {
11
+ case 'threads':
12
+ case 'process':
13
+ return process.env.PARCEL_WORKER_BACKEND;
14
+ }
15
+
10
16
  try {
11
17
  require('worker_threads');
12
18
 
package/lib/bus.js CHANGED
@@ -5,13 +5,21 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _events = _interopRequireDefault(require("events"));
8
+ function _events() {
9
+ const data = _interopRequireDefault(require("events"));
10
+
11
+ _events = function () {
12
+ return data;
13
+ };
14
+
15
+ return data;
16
+ }
9
17
 
10
18
  var _childState = require("./childState");
11
19
 
12
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
21
 
14
- class Bus extends _events.default {
22
+ class Bus extends _events().default {
15
23
  emit(event, ...args) {
16
24
  if (_childState.child) {
17
25
  _childState.child.workerApi.callMaster({