The Q6600
Benchmarks Game

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: []
}