k-nucleotide TypeScript #3 program
source code
/* The Computer Language Benchmarks Game
https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
Based on Node js #2 implementation of Jesse Millikan, Matt Baker and Roman Pletnev
Contributed by Dani Biro
*/
'use strict';
const rd = require('readline');
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
function RefNum (num) { this.num = num; }
RefNum.prototype.toString = function () { return this.num.toString(); };
function sliceToInt (seq, start, end) {
let val = 0;
for (let i = start; i < end; ++i) {
val = (val * 4) + seq[i];
}
return val;
}
function bitwiseTrimLeft (value, length) {
return (
value - (Math.floor(value / Math.pow(2, length)) * Math.pow(2, length))
);
}
const keyMap = ['a', 't', 'c', 'g'];
function keyToString (value, length) {
const str = new Array(length);
for (let i = 0; i < length; ++i) {
const key = bitwiseTrimLeft(value, 2);
str[length - i - 1] = keyMap[key];
value = Math.floor(value / 4);
}
return str.join('').toUpperCase();
}
function frequency (seq, length) {
const freq = new Map();
const n = seq.length - length + 1;
const maskLength = length * 2 - 2;
let key = sliceToInt(seq, 0, length);
for (let i = length; i < n; ++i) {
const cur = freq.get(key);
if (cur === undefined) {
freq.set(key, new RefNum(1));
} else {
cur.num++;
}
key = bitwiseTrimLeft(key, maskLength) * 4 + seq[i];
}
return freq;
}
function sort (seq, length) {
const f = frequency(seq, length);
const keys = Array.from(f.keys());
const n = seq.length - length + 1;
const res = [];
keys.sort((a, b) => f.get(b) - f.get(a));
const len = keys.length;
for (let i = 0; i < len; ++i) {
const key = keys[i];
res.push(`${keyToString(key, length)} ${(f.get(key) * 100 / n).toFixed(3)}\n`);
}
res.push('\n');
return res.join('');
}
function toTransformedBuffer (str) {
const sharedArray = new Uint8Array(new SharedArrayBuffer(str.length));
for (let i = 0; i < sharedArray.length; ++i) {
switch (str.charAt(i)) {
case 't':
sharedArray[i] = 1;
break;
case 'c':
sharedArray[i] = 2;
break;
case 'g':
sharedArray[i] = 3;
break;
}
}
return sharedArray;
}
function find (seq, str) {
const f = frequency(seq, str.length);
const buffer = toTransformedBuffer(str);
return `${f.get(sliceToInt(buffer, 0, str.length)) || 0}\t${str.toUpperCase()}\n`;
}
function master () {
const results = new Array(4);
let lines = [];
let reading = false;
let jobs = 4;
let currentLen = 0;
let processing = false;
let totalBack = 0;
const BUFFER_LIMIT = 1024 * 128;
let buffers = [];
const finishReading = function () {
const sharedArray = new Uint8Array(new SharedArrayBuffer(totalBack));
let index = 0;
for (let i = 0; i < buffers.length; ++i) {
sharedArray.set(buffers[i], index);
index += buffers[i].length;
}
processing = true;
buffers = [];
lines = [];
for (let i = 0; i < 4; ++i) {
workers[i].postMessage({ seq: sharedArray });
}
};
const messageHandler = function (workerId) {
return function (message) {
if (!processing) {
buffers.push(message.buf);
totalBack += message.buf.length;
if (message.done) {
finishReading();
}
} else {
results[workerId] = message;
if (--jobs === 0) {
process.stdout.write(results.join(''));
process.exit(0);
}
}
};
};
const workers = [...Array(jobs)].map((_, workerId) => {
const worker = new Worker(__filename, { workerData: { workerId } });
worker.on('message', messageHandler(workerId));
return worker;
});
const readOnThread = function (done) {
const str = lines.join('');
const sharedArray = new Uint8Array(new SharedArrayBuffer(str.length));
sharedArray.set(Buffer.from(str, 'ascii'));
workers[0].postMessage({ buf: sharedArray, done });
};
const lineHandler = function (line) {
if (reading) {
lines.push(line);
currentLen += line.length;
if (currentLen > BUFFER_LIMIT) {
readOnThread(false);
lines = [];
currentLen = 0;
}
} else if (line[0] === '>') {
reading = line.slice(0, 6) === '>THREE';
};
};
rd.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
})
.on('line', lineHandler)
.on('close', function () {
readOnThread(true);
});
}
function transformArray (arr) {
for (let i = 0; i < arr.length; ++i) {
const x = arr[i];
if (x === 97) {
arr[i] = 0;
} else if (x === 116) {
arr[i] = 1;
} else if (x === 99) {
arr[i] = 2;
} else {
arr[i] = 3;
}
}
}
function worker () {
parentPort.on('message', (message) => {
if (message.buf) {
transformArray(message.buf);
parentPort.postMessage(message);
} else {
const seq = message.seq;
const res = [];
switch (workerData.workerId) {
case 0:
res.push(sort(seq, 1));
res.push(sort(seq, 2));
res.push(find(seq, 'ggt'));
break;
case 1:
res.push(find(seq, 'ggta'));
res.push(find(seq, 'ggtatt'));
break;
case 2:
res.push(find(seq, 'ggtattttaatt'));
break;
case 3:
res.push(find(seq, 'ggtattttaatttatagt'));
break;
}
parentPort.postMessage(res.join(''));
}
});
}
if (isMainThread) {
master();
} else {
worker();
}
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
Version 3.9.2
node.js v14.2.0
Wed, 13 May 2020 17:30:08 GMT
MAKE:
mv knucleotide.typescript-3.typescript knucleotide.typescript-3.ts
/opt/src/node-v14.2.0-linux-x64/bin/tsc --strict --noEmitOnError --removeComments knucleotide.typescript-3.ts
knucleotide.typescript-3.ts(11,9): error TS2451: Cannot redeclare block-scoped variable 'Worker'.
knucleotide.typescript-3.ts(13,18): error TS7006: Parameter 'num' implicitly has an 'any' type.
knucleotide.typescript-3.ts(13,25): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
knucleotide.typescript-3.ts(16,22): error TS7006: Parameter 'seq' implicitly has an 'any' type.
knucleotide.typescript-3.ts(16,27): error TS7006: Parameter 'start' implicitly has an 'any' type.
knucleotide.typescript-3.ts(16,34): error TS7006: Parameter 'end' implicitly has an 'any' type.
knucleotide.typescript-3.ts(24,27): error TS7006: Parameter 'value' implicitly has an 'any' type.
knucleotide.typescript-3.ts(24,34): error TS7006: Parameter 'length' implicitly has an 'any' type.
knucleotide.typescript-3.ts(32,23): error TS7006: Parameter 'value' implicitly has an 'any' type.
knucleotide.typescript-3.ts(32,30): error TS7006: Parameter 'length' implicitly has an 'any' type.
knucleotide.typescript-3.ts(42,21): error TS7006: Parameter 'seq' implicitly has an 'any' type.
knucleotide.typescript-3.ts(42,26): error TS7006: Parameter 'length' implicitly has an 'any' type.
knucleotide.typescript-3.ts(51,21): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.
knucleotide.typescript-3.ts(60,16): error TS7006: Parameter 'seq' implicitly has an 'any' type.
knucleotide.typescript-3.ts(60,21): error TS7006: Parameter 'length' implicitly has an 'any' type.
knucleotide.typescript-3.ts(77,31): error TS7006: Parameter 'str' implicitly has an 'any' type.
knucleotide.typescript-3.ts(95,16): error TS7006: Parameter 'seq' implicitly has an 'any' type.
knucleotide.typescript-3.ts(95,21): error TS7006: Parameter 'str' implicitly has an 'any' type.
knucleotide.typescript-3.ts(103,7): error TS7034: Variable 'lines' implicitly has type 'any[]' in some locations where its type cannot be determined.
knucleotide.typescript-3.ts(110,7): error TS7034: Variable 'buffers' implicitly has type 'any[]' in some locations where its type cannot be determined.
knucleotide.typescript-3.ts(116,23): error TS7005: Variable 'buffers' implicitly has an 'any[]' type.
knucleotide.typescript-3.ts(117,16): error TS7005: Variable 'buffers' implicitly has an 'any[]' type.
knucleotide.typescript-3.ts(127,36): error TS7006: Parameter 'workerId' implicitly has an 'any' type.
knucleotide.typescript-3.ts(128,22): error TS7006: Parameter 'message' implicitly has an 'any' type.
knucleotide.typescript-3.ts(146,45): error TS2345: Argument of type '{ workerData: { workerId: number; }; }' is not assignable to parameter of type 'WorkerOptions'.
Object literal may only specify known properties, and 'workerData' does not exist in type 'WorkerOptions'.
knucleotide.typescript-3.ts(147,12): error TS2339: Property 'on' does not exist on type 'Worker'.
knucleotide.typescript-3.ts(151,34): error TS7006: Parameter 'done' implicitly has an 'any' type.
knucleotide.typescript-3.ts(152,17): error TS7005: Variable 'lines' implicitly has an 'any[]' type.
knucleotide.typescript-3.ts(158,33): error TS7006: Parameter 'line' implicitly has an 'any' type.
knucleotide.typescript-3.ts(183,26): error TS7006: Parameter 'arr' implicitly has an 'any' type.
knucleotide.typescript-3.ts(199,29): error TS7006: Parameter 'message' implicitly has an 'any' type.
../../../../../opt/src/node-v14.2.0-linux-x64/lib/node_modules/typescript/lib/lib.dom.d.ts(18599,11): error TS2451: Cannot redeclare block-scoped variable 'Worker'.
../../../../../opt/src/node-v14.2.0-linux-x64/lib/node_modules/typescript/lib/lib.dom.d.ts(18617,13): error TS2451: Cannot redeclare block-scoped variable 'Worker'.
make: [/home/dunham/8000-benchmarksgame/nanobench/makefiles/u64q.programs.Makefile:393: knucleotide.typescript-3.typescript_run] Error 1 (ignored)
6.05s to complete and log all make actions
COMMAND LINE:
/opt/src/node-v14.2.0-linux-x64/bin/node --use_strict knucleotide.typescript-3.js 0 < knucleotide-input250000.txt
PROGRAM FAILED
PROGRAM OUTPUT:
internal/modules/cjs/loader.js:1023
throw err;
^
Error: Cannot find module '/home/dunham/benchmarksgame_quadcore/knucleotide/tmp/knucleotide.typescript-3.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1020:15)
at Function.Module._load (internal/modules/cjs/loader.js:890:27)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}