@parcel/workers 2.0.0-nightly.92 → 2.0.1

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,80 +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, "profiler", void 0);
83
-
84
- _defineProperty(this, "workerApi", {
85
- callMaster: async (request, awaitResponse = true) => {
86
- // $FlowFixMe
87
- let result = await this.processRequest(_objectSpread({}, request, {
88
- awaitResponse
89
- }));
90
- return (0, _core.deserialize)((0, _core.serialize)(result));
91
- },
92
- createReverseHandle: fn => this.createReverseHandle(fn),
93
- callChild: (childId, request) => new Promise((resolve, reject) => {
94
- (0, _nullthrows.default)(this.workers.get(childId)).call(_objectSpread({}, request, {
95
- resolve,
96
- reject,
97
- retries: 0
98
- }));
99
- }),
100
- getSharedReference: ref => this.sharedReferences.get(ref)
101
- });
102
-
103
- this.options = _objectSpread({
120
+ this.options = {
104
121
  maxConcurrentWorkers: WorkerFarm.getNumWorkers(),
105
122
  maxConcurrentCallsPerWorker: WorkerFarm.getConcurrentCallsPerWorker(),
106
123
  forcedKillTime: 500,
107
124
  warmWorkers: false,
108
125
  useLocalWorker: true,
109
126
  // TODO: setting this to false makes some tests fail, figure out why
110
- backend: (0, _backend.detectBackend)()
111
- }, farmOptions);
127
+ backend: (0, _backend.detectBackend)(),
128
+ ...farmOptions
129
+ };
112
130
 
113
131
  if (!this.options.workerPath) {
114
132
  throw new Error('Please provide a worker path!');
@@ -116,10 +134,35 @@ class WorkerFarm extends _events.default {
116
134
 
117
135
 
118
136
  this.localWorker = require(this.options.workerPath);
137
+ this.localWorkerInit = this.localWorker.childInit != null ? this.localWorker.childInit() : null;
119
138
  this.run = this.createHandle('run');
120
139
  this.startMaxWorkers();
121
140
  }
122
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
+
123
166
  warmupWorker(method, args) {
124
167
  // Workers are already stopping
125
168
  if (this.ending) {
@@ -147,7 +190,7 @@ class WorkerFarm extends _events.default {
147
190
  }
148
191
 
149
192
  createHandle(method) {
150
- return (...args) => {
193
+ return async (...args) => {
151
194
  // Child process workers are slow to start (~600ms).
152
195
  // While we're waiting, just run on the main thread.
153
196
  // This significantly speeds up startup time.
@@ -158,7 +201,13 @@ class WorkerFarm extends _events.default {
158
201
  this.warmupWorker(method, args);
159
202
  }
160
203
 
161
- 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
+
162
211
  return this.localWorker[method](this.workerApi, ...processedArgs);
163
212
  }
164
213
  };
@@ -168,6 +217,8 @@ class WorkerFarm extends _events.default {
168
217
  // Handle ipc errors
169
218
  if (error.code === 'ERR_IPC_CHANNEL_CLOSED') {
170
219
  return this.stopWorker(worker);
220
+ } else {
221
+ _logger().default.error(error, '@parcel/workers');
171
222
  }
172
223
  }
173
224
 
@@ -175,9 +226,10 @@ class WorkerFarm extends _events.default {
175
226
  let worker = new _Worker.default({
176
227
  forcedKillTime: this.options.forcedKillTime,
177
228
  backend: this.options.backend,
178
- patchConsole: this.options.patchConsole
229
+ shouldPatchConsole: this.options.shouldPatchConsole,
230
+ sharedReferences: this.sharedReferences
179
231
  });
180
- worker.fork((0, _nullthrows.default)(this.options.workerPath));
232
+ worker.fork((0, _nullthrows().default)(this.options.workerPath));
181
233
  worker.on('request', data => this.processRequest(data, worker));
182
234
  worker.on('ready', () => this.processQueue());
183
235
  worker.on('response', () => this.processQueue());
@@ -212,7 +264,9 @@ class WorkerFarm extends _events.default {
212
264
  this.startChild();
213
265
  }
214
266
 
215
- 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) {
216
270
  if (!this.callQueue.length) {
217
271
  break;
218
272
  }
@@ -239,7 +293,9 @@ class WorkerFarm extends _events.default {
239
293
  let mod;
240
294
 
241
295
  if (handleId != null) {
242
- 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);
243
299
  } else if (location) {
244
300
  // $FlowFixMe this must be dynamic
245
301
  mod = require(location);
@@ -258,27 +314,26 @@ class WorkerFarm extends _events.default {
258
314
  idx,
259
315
  type: 'response',
260
316
  contentType: 'error',
261
- content: (0, _diagnostic.anyToDiagnostic)(e)
317
+ content: (0, _diagnostic().anyToDiagnostic)(e)
262
318
  });
263
319
 
264
320
  let result;
265
321
 
266
322
  if (method == null) {
267
323
  try {
268
- result = responseFromContent((await mod(...args)));
324
+ result = responseFromContent(await mod(...args));
269
325
  } catch (e) {
270
326
  result = errorResponseFromError(e);
271
327
  }
272
328
  } else {
273
329
  // ESModule default interop
274
- // $FlowFixMe
275
330
  if (mod.__esModule && !mod[method] && mod.default) {
276
331
  mod = mod.default;
277
332
  }
278
333
 
279
334
  try {
280
335
  // $FlowFixMe
281
- result = responseFromContent((await mod[method](...args)));
336
+ result = responseFromContent(await mod[method](...args));
282
337
  } catch (e) {
283
338
  result = errorResponseFromError(e);
284
339
  }
@@ -289,7 +344,7 @@ class WorkerFarm extends _events.default {
289
344
  worker.send(result);
290
345
  } else {
291
346
  if (result.contentType === 'error') {
292
- throw new _diagnostic.default({
347
+ throw new (_diagnostic().default)({
293
348
  diagnostic: result.content
294
349
  });
295
350
  }
@@ -318,6 +373,7 @@ class WorkerFarm extends _events.default {
318
373
 
319
374
  async end() {
320
375
  this.ending = true;
376
+ await Promise.all(Array.from(this.workers.values()).map(worker => this.stopWorker(worker)));
321
377
 
322
378
  for (let handle of this.handles.values()) {
323
379
  handle.dispose();
@@ -325,7 +381,7 @@ class WorkerFarm extends _events.default {
325
381
 
326
382
  this.handles = new Map();
327
383
  this.sharedReferences = new Map();
328
- await Promise.all(Array.from(this.workers.values()).map(worker => this.stopWorker(worker)));
384
+ this.sharedReferencesByValue = new Map();
329
385
  this.ending = false;
330
386
  }
331
387
 
@@ -346,28 +402,25 @@ class WorkerFarm extends _events.default {
346
402
 
347
403
  createReverseHandle(fn) {
348
404
  let handle = new _Handle.default({
349
- fn,
350
- workerApi: this.workerApi
405
+ fn
351
406
  });
352
407
  this.handles.set(handle.id, handle);
353
408
  return handle;
354
409
  }
355
410
 
356
- async createSharedReference(value) {
411
+ async createSharedReference(value, // An optional, pre-serialized representation of the value to be used
412
+ // in its place.
413
+ buffer) {
357
414
  let ref = referenceId++;
358
415
  this.sharedReferences.set(ref, value);
416
+ this.sharedReferencesByValue.set(value, ref);
417
+ let toSend = buffer ? buffer.buffer : value;
359
418
  let promises = [];
360
419
 
361
420
  for (let worker of this.workers.values()) {
362
- promises.push(new Promise((resolve, reject) => {
363
- worker.call({
364
- method: 'createSharedReference',
365
- args: [ref, value],
366
- resolve,
367
- reject,
368
- retries: 0
369
- });
370
- }));
421
+ if (worker.ready) {
422
+ promises.push(worker.sendSharedReference(ref, toSend));
423
+ }
371
424
  }
372
425
 
373
426
  await Promise.all(promises);
@@ -375,6 +428,7 @@ class WorkerFarm extends _events.default {
375
428
  ref,
376
429
  dispose: () => {
377
430
  this.sharedReferences.delete(ref);
431
+ this.sharedReferencesByValue.delete(value);
378
432
  let promises = [];
379
433
 
380
434
  for (let worker of this.workers.values()) {
@@ -384,6 +438,7 @@ class WorkerFarm extends _events.default {
384
438
  args: [ref],
385
439
  resolve,
386
440
  reject,
441
+ skipReadyCheck: true,
387
442
  retries: 0
388
443
  });
389
444
  }));
@@ -404,7 +459,8 @@ class WorkerFarm extends _events.default {
404
459
  args: [],
405
460
  resolve,
406
461
  reject,
407
- retries: 0
462
+ retries: 0,
463
+ skipReadyCheck: true
408
464
  });
409
465
  }));
410
466
  }
@@ -430,15 +486,16 @@ class WorkerFarm extends _events.default {
430
486
  args: [],
431
487
  resolve,
432
488
  reject,
433
- retries: 0
489
+ retries: 0,
490
+ skipReadyCheck: true
434
491
  });
435
492
  }));
436
493
  }
437
494
 
438
495
  var profiles = await Promise.all(promises);
439
496
  let trace = new _Trace.default();
440
- let filename = `profile-${profileId++}.trace`;
441
- let stream = trace.pipe(_fs.default.createWriteStream(filename));
497
+ let filename = `profile-${getTimeId()}.trace`;
498
+ let stream = trace.pipe(_fs().default.createWriteStream(filename));
442
499
 
443
500
  for (let profile of profiles) {
444
501
  trace.addCPUProfile(names.shift(), profile);
@@ -449,14 +506,60 @@ class WorkerFarm extends _events.default {
449
506
  stream.once('finish', resolve);
450
507
  });
451
508
 
452
- _logger.default.info({
509
+ _logger().default.info({
453
510
  origin: '@parcel/workers',
454
- message: `Wrote profile to ${filename}`
511
+ message: (0, _diagnostic().md)`Wrote profile to ${filename}`
455
512
  });
456
513
  }
457
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
+
458
561
  static getNumWorkers() {
459
- 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);
460
563
  }
461
564
 
462
565
  static isWorker() {
@@ -464,14 +567,19 @@ class WorkerFarm extends _events.default {
464
567
  }
465
568
 
466
569
  static getWorkerApi() {
467
- (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');
468
571
  return _childState.child.workerApi;
469
572
  }
470
573
 
471
574
  static getConcurrentCallsPerWorker() {
472
- return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 5;
575
+ return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 30;
473
576
  }
474
577
 
475
578
  }
476
579
 
477
- 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({