Skip to content

Commit

Permalink
klesun#8 Try sending transpilation jobs to separate workers
Browse files Browse the repository at this point in the history
For some reason it did not become faster at all, possiblyI am doing something wrong
  • Loading branch information
klesun committed Feb 16, 2020
1 parent 78899d7 commit a22a598
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 47 deletions.
45 changes: 45 additions & 0 deletions src/TranspileWorker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//import ParseTsModule from "./actions/ParseTsModule.js";

const main = () => {
self.importScripts(
'https://klesun-misc.github.io/TypeScript/lib/typescriptServices.js',
'https://klesun-productions.com/entry/ts-browser/src/UrlPathResolver_sideEffects.js',
'https://klesun-productions.com/entry/ts-browser/src/actions/ParseTsModule_sideEffects.js'
);
const org = self.org;
/** @type {ts} */
const ts = self.ts;

const onmessage = ({data}) => {
if (data.messageType === 'parseTsModule') {
const parsed = org.klesun.tsBrowser.ParseTsModule_sideEffects({
...data.messageData, ts: ts,
addPathToUrl: org.klesun.tsBrowser.addPathToUrl,
});
self.postMessage({
messageType: 'parseTsModule',
messageData: parsed,
});
}
};

self.onmessage = evt => {
try {
onmessage(evt);
} catch (exc) {
self.postMessage({
messageType: 'error',
messageData: {
message: exc.message,
stack: exc.stack,
},
});
}
};
};

try {
main();
} catch (exc) {
self.postMessage('Failed to initialize worker - ' + exc + '\n' + exc.stack);
}
38 changes: 3 additions & 35 deletions src/UrlPathResolver.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,8 @@

const addPathToUrl = (path, baseUrl) => {
let result;
if (path.startsWith('/') || path.match(/^https?:\/\//)) {
// full path from the site root
result = path;
} else {
const urlParts = baseUrl.split('/');
const pathParts = path.split('/');
import './UrlPathResolver_sideEffects.js';
const org = window.org;

if (urlParts.slice(-1)[0] !== '') {
// does not end with a slash - script, not directory
urlParts.pop();
}

// getting rid of trailing slashes if any
while (pathParts[0] === '') pathParts.shift();
while (urlParts.slice(-1)[0] === '') urlParts.pop();

const resultParts = [...urlParts];
for (const pathPart of pathParts) {
if (pathPart === '..' && resultParts.slice(-1)[0] !== '..') {
while (resultParts.slice(-1)[0] === '.') resultParts.pop();
if (resultParts.length > 0) {
resultParts.pop();
} else {
resultParts.push('..');
}
} else if (pathPart !== '.') {
resultParts.push(pathPart);
}
}
result = resultParts.join('/') || '.';
}

return result;
};
const addPathToUrl = org.klesun.tsBrowser.addPathToUrl;

export {
addPathToUrl,
Expand Down
48 changes: 48 additions & 0 deletions src/UrlPathResolver_sideEffects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

var org = org || {};
org.klesun = org.klesun || {};
org.klesun.tsBrowser = org.klesun.tsBrowser || {};

org.klesun.tsBrowser.addPathToUrl = (path, baseUrl) => {
let result;
if (path.startsWith('/') || path.match(/^https?:\/\//)) {
// full path from the site root
result = path;
} else {
const urlParts = baseUrl.split('/');
const pathParts = path.split('/');

if (urlParts.slice(-1)[0] !== '') {
// does not end with a slash - script, not directory
urlParts.pop();
}

// getting rid of trailing slashes if any
while (pathParts[0] === '') pathParts.shift();
while (urlParts.slice(-1)[0] === '') urlParts.pop();

const resultParts = [...urlParts];
for (const pathPart of pathParts) {
if (pathPart === '..' && resultParts.slice(-1)[0] !== '..') {
while (resultParts.slice(-1)[0] === '.') resultParts.pop();
if (resultParts.length > 0) {
resultParts.pop();
} else {
resultParts.push('..');
}
} else if (pathPart !== '.') {
resultParts.push(pathPart);
}
}
result = resultParts.join('/') || '.';
}

return result;
};

const isWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
if (isWorker) {
self.org = org;
} else {
window.org = org;
}
67 changes: 61 additions & 6 deletions src/WorkerManager.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
import {oneSuccess} from "./utils.js";
import ParseTsModule from "./actions/ParseTsModule.js";
import {addPathToUrl} from "./UrlPathResolver.js";


const EXPLICIT_EXTENSIONS = ['ts', 'js', 'tsx', 'jsx'];

const WorkerManager = ({ts, compilerOptions}) => {
const NUM_OF_WORKERS = 2;

const workers = [...Array(NUM_OF_WORKERS).keys()].map(i => {
const scriptUrl = import.meta.url;
const workerUrl = addPathToUrl('./TranspileWorker.js', scriptUrl);
const worker = new Worker(workerUrl);
worker.onmessage = ({data}) => {
console.log('Received event from worker #' + i, data);
};
return {
parseTsModule: (params) => new Promise((ok, err) => {
worker.postMessage({
messageType: 'parseTsModule',
messageData: params,
});
worker.onmessage = ({data}) => {
if (data.messageType === 'parseTsModule') {
ok(data.messageData);
} else {
const msg = 'Unexpected parseTsModule() worker response';
const exc = new Error(msg);
exc.data = data;
err(exc);
}
};
}),
};
});

const workerCallbackQueue = [];
const freeWorkers = new Set(workers);

const withFreeWorker = (action) => new Promise((ok, err) => {
workerCallbackQueue.push(
worker => Promise.resolve()
.then(() => action(worker))
.then(ok).catch(err)
);
const checkFree = () => {
if (freeWorkers.size > 0 &&
workerCallbackQueue.length > 0
) {
const worker = [...freeWorkers][0];
freeWorkers.delete(worker);
const callback = workerCallbackQueue.shift();
callback(worker).finally(() => {
freeWorkers.add(worker);
checkFree();
});
}
};
checkFree();
});

const WorkerManager = ({compilerOptions}) => {
const fetchModuleSrc = (url) => {
// typescript does not allow specifying extension in the import, but react
// files may have .tsx extension rather than .ts, so have to check both
Expand All @@ -31,10 +85,11 @@ const WorkerManager = ({ts, compilerOptions}) => {
};

const parseInWorker = async ({url, fullUrl, tsCode}) => {
// TODO: actual workers!
const {isJsSrc, staticDependencies, jsCode} =
ParseTsModule({fullUrl, ts, tsCode, compilerOptions});
return {url, isJsSrc, staticDependencies, jsCode};
return withFreeWorker(worker => worker.parseTsModule({
fullUrl, tsCode, compilerOptions,
}).then(({isJsSrc, staticDependencies, jsCode}) => {
return {url, isJsSrc, staticDependencies, jsCode};
}));
};

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

import {addPathToUrl} from "../UrlPathResolver.js";
var org = org || {};
org.klesun = org.klesun || {};
org.klesun.tsBrowser = org.klesun.tsBrowser || {};

/**
* @param {ts.ImportClause} importClause - `{Field1, Field2}`
Expand Down Expand Up @@ -30,8 +32,8 @@ const es6ToDestr = (tsCode, importClause) => {
}
};

export const CACHE_LOADED = 'ts-browser-loaded-modules';
export const IMPORT_DYNAMIC = 'ts-browser-import-dynamic';
const CACHE_LOADED = 'ts-browser-loaded-modules';
const IMPORT_DYNAMIC = 'ts-browser-import-dynamic';

const transformStatement = ({statement, sourceFile, baseUrl, ts}) => {
const getNodeText = node => {
Expand Down Expand Up @@ -81,7 +83,7 @@ const transformStatement = ({statement, sourceFile, baseUrl, ts}) => {
* @param {ts} ts
* @param {ts.CompilerOptions} compilerOptions
*/
const ParseTsModule = ({fullUrl, tsCode, compilerOptions, ts}) => {
org.klesun.tsBrowser.ParseTsModule_sideEffects = ({fullUrl, tsCode, compilerOptions, ts, addPathToUrl}) => {
const extension = fullUrl.replace(/^.*\./, '');
const sourceFile = ts.createSourceFile(
'ololo.' + extension, tsCode, compilerOptions.target
Expand Down Expand Up @@ -122,4 +124,3 @@ const ParseTsModule = ({fullUrl, tsCode, compilerOptions, ts}) => {
return {isJsSrc, staticDependencies, jsCode};
};

export default ParseTsModule;
4 changes: 3 additions & 1 deletion src/ts-browser.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

import {b64EncodeUnicode} from "./utils.js";
import {addPathToUrl} from "./UrlPathResolver.js";
import {CACHE_LOADED, IMPORT_DYNAMIC} from "./actions/ParseTsModule.js";
import WorkerManager from "./WorkerManager.js";

const CACHE_LOADED = 'ts-browser-loaded-modules';
const IMPORT_DYNAMIC = 'ts-browser-import-dynamic';

/**
* @module ts-browser - like ts-node, this tool allows you
* to require typescript files and compiles then on the fly
Expand Down

0 comments on commit a22a598

Please sign in to comment.