Open6

Node.js Tips

DaiDai

ファイル

ファイル削除

メモリ上で処理しきれないため、一度ディスクに書き出す処理を行い、ファイルが残らないように削除したい場合に使える。

fs.unlink("path/to/file", (err) => {
  if (err) throw err;
});

ディレクトリ削除

fs.rmdirSync("path/to/dir", { recursive: true });
DaiDai

メモリ

使用メモリを出力する関数

out of memory した時などの調査用。

// Output e.g.) rss: 152.06 MB, heapTotal: 106.01 MB, heapUsed: 81.61 MB, external: 2.03 MB, arrayBuffers: 0.48 MB <= test
showMemory(message: string) {
  const usage = process.memoryUsage();
  const log = [];
  for (const [key, value] of Object.entries(usage)) {
    log.push(`${key}: ${Math.round((value / 1024 / 1024) * 100) / 100} MB`);
  }
  console.log(`${log.join(", ")} <= ${message}`);
}

オブジェクトのメモリを出力

console.log(JSON.stringify(targetObject).length / 1000 / 1000); // MB表示

厳密ではないかもしれないので注意。ただし、Lambdaのペイロードの制限や、MySQLの max_allowed_packet の制限と同じ粒度で測定できることは確認済み(max_allowed_packet=4MBの場合、上記で4MB以上が測定されるとエラーが発生する)。

オブジェクトが大きすぎてMAX_STRING_LENGTH(V8エンジンのMAX_STRING_LENGTH参照)に引っかかる場合、for文でlengthを足し合わせれば良い。

こういう記事もあったがJSON.stringifyと比べて1/2ほどになるので定かではない。

V8エンジンのMAX_STRING_LENGTH

JSON.stringify などで巨大なオブジェクトをString化しようとしたりすると、"RangeError: Invalid string length" が発生する。Node.jsではなく、V8エンジンで MAX_STRING_LENGTH が定められており、先のエラーはその上限を超えたから発生している。変更することはできないが、プログラムから下記でStringインスタンスの上限を確認可能。

console.log(`MAX: ${require("buffer").constants.MAX_STRING_LENGTH}`); // => 538 MB in v14.15.3

V8エンジンのメモリ

console.log(Math.floor(require("v8").getHeapStatistics().heap_size_limit / 1024 / 1024));
DaiDai

TypeORM

SQL文の表示

IN句には対応していないので注意。

const q = query.getQueryAndParameters();
let sql = q[0];
const parameters = q[1];
parameters.forEach((p) => {
  sql = sql.replace("?", `'${p}'`);
});
console.log(sql);
DaiDai

配列

連番の配列を生成する関数

/**
 * createSerialNumbers(0, 5) => [ 0, 1, 2, 3, 4 ]
 * createSerialNumbers(5, 10) => [ 5, 6, 7, 8, 9 ]
 */
function createSerialNumbers(startIndex: number, endIndex: number): number[] {
  if (startIndex > endIndex)
    throw new Error("startIndex should be less than endIndex");
  return [...Array(endIndex - startIndex).keys()].map((i) => i + startIndex);
}
DaiDai

時間計測

イケてるやり方

console.time("counter");
console.timeEnd("counter"); // => counter: 4.817ms

イケてないやり方

const start: any = new Date();
const end = (new Date() as any) - start;
console.log("Execution time: %dms", end);
DaiDai

Nodeアプリの実行

ts-nodeで --max-old-space-size オプションを渡す

--max-old-space-size は node のオプションなので ts-node で下記のように渡すことはできない。
ts-node --transpile-only --max-old-space-size=4096 src/index.ts

公式ドキュメントのやり方

NODE_OPTIONS='--max-old-space-size=4096' ts-node --transpile-only src/index.ts

上記でいいと思う。

公式のイシューで提案されてるやり方

node --max-old-space-size=4096 -- node_modules/.bin/ts-node --transpile-only src/index.ts