44

ノードで開発するときは、常にブロッキング(同期)関数を避けて非同期関数を使用する必要があることを知っていますが、それらがどのように比較されるかを確認するために少しテストします。

i18nデータ(日付と時刻の形式など)を含むjsonファイルを開き、そのデータを、このデータを使用してビューの数値などを形式化するクラスに渡す必要があります。

クラスのすべてのメソッドをコールバック内にラップし始めるのはちょっと厄介なので、可能であれば、代わりに同期バージョンを使用します。

console.time('one');
console.time('two');
fs.readFile( this.dir + "/" + locale + ".json", function (err, data) {
  if (err) cb( err );
  console.timeEnd('one');
});
var data = fs.readFileSync( this.dir + "/" + locale + ".json" );
console.timeEnd('two');

これにより、コンソールに次の行が表示されます。

two: 1ms
one: 159ms

fs.readFileSyncはfs.readFileよりも約150倍高速で、50KBのjsonファイル(縮小)をロードするのに約1msかかるようです。私のすべてのjsonファイルは約50-100KBです。

また、このjsonデータをメモ化するか、セッションに保存して、ファイルがセッションごとに1回だけ(またはユーザーがロケールを変更したときに)読み取られるようにすることも考えていました。私はそれをどのように行うのか完全にはわかりません、それはただの考えです。

fs.readFileSync私の場合は使用しても大丈夫ですか、それとも後で問題が発生しますか?

4

5 に答える 5

75

いいえ、説明したように、ノードサーバーでブロッキングAPI呼び出しを使用することはできません。多くの同時接続に対するサイトの応答性は大きな打撃を受けるでしょう。また、ノードの第1の原則に露骨に違反しているだけです。

ノードが機能するための鍵は、IOを待機している間、CPU/メモリ処理を同時に実行していることです。これには、非同期呼び出しのみが必要です。したがって、100個のクライアントが100個のJSONファイルを読み取る場合、ノードはOSにそれらの100個のファイルを読み取るように要求できますが、OSがファイルデータを返すのを待っている間、ノードはそれらの100個のネットワーク要求の他の側面を処理できます。そこに単一の同期呼び出しがある場合、その操作が完了する間、すべてのクライアント処理は完全に停止します。したがって、クライアント番号100の接続は、クライアント1、2、3、4などのファイルを順番に読み取る間、何も処理せずに待機します。これはフェイルビルです。

別の例えがあります。あなたがレストランに行き、唯一の顧客である場合、一人の人があなたに座って注文を取り、それを調理し、あなたに提供し、そしてホストとの取引の調整オーバーヘッドなしで請求書を処理した場合、あなたはおそらくより速いサービスを受けるでしょう/ホステス、サーバー、ヘッドシェフ、料理人、レジ係など。ただし、レストランに100人の顧客がいる場合、追加の調整により、物事が並行して行われ、レストランの全体的な応答性は、1人の場合よりもはるかに向上します。 100人の顧客を自分で処理しようとしています。

于 2012-12-11T15:42:36.590 に答える
12

非同期読み取りのコールバックを同期読み取りでブロックしています。シングルスレッドを覚えておいてください。今では時差がまだ素晴らしいことを理解していますが、はるかに長いファイルを試してみて、多くのクライアントが同じことを行うことを想像してみてください。そうすれば、オーバーヘッドが報われます。それはあなたの質問に答えるはずです、はい、あなたがブロッキングIOで何千ものリクエストを処理しているならあなたは問題にぶつかるでしょう。

于 2012-12-11T15:18:17.897 に答える
1

はい、それは正しいです。サーバー側の環境で非同期の方法を処理することです。ただし、クライアント側のJSプロジェクトのようにビルドを生成するなど、ユースケースが異なる場合は、さまざまなフレーバーのJSONファイルの読み取りと書き込みを行います。

それほど影響はありません。デプロイ用の縮小ビルドを作成するための迅速な方法が必要でしたが(ここでは同期が全体像になります)。 詳細とライブラリについて

于 2019-08-01T08:03:15.223 に答える
0

たくさんの時間とたくさんの学習と練習の後で、私はもう一度試しました、そして私は答えを見つけました、そして私はいくつかの例を示すことができます:

const fs = require('fs');

const syncTest = () => {
    let startTime = +new Date();
    const results = [];
    const files = [];

    for (let i=0, len=4; i<len; i++) {
        files.push(fs.readFileSync(`file-${i}.txt`));
    };

    for (let i=0, len=360; i<len; i++) results.push(Math.sin(i), Math.cos(i));
    console.log(`Sync version: ${+new Date() - startTime}`);
};

const asyncTest = () => {
    let startTime = +new Date();
    const results = [];
    const files = [];

    for (let i=0, len=4; i<len; i++) {
        fs.readFile(`file-${i}.txt`, file => files.push(file));
    };

    for (let i=0, len=360; i<len; i++) results.push(Math.sin(i), Math.cos(i));

    console.log(`Async version: ${+new Date() - startTime}`);
};

syncTest();
asyncTest();
于 2018-10-06T16:54:35.680 に答える
-1

SDカードにある3つの異なるファイルをダウンロードするために、fs.readFileSync()とfs.readFile()の速度の実際の測定可能な違いを確認しようとしましたが、このダウンロードの間に数学計算を追加しました。同じファイルを3回ダウンロードするなどの簡単な操作でも、ノードが高速で、このファイルを1回ダウンロードするのに必要な時間に近い場合に、ノードの画像に常に表示される速度の違いはどこにあるのかわかりません。 。

これは、ファイルのダウンロード中にサーバーが他の仕事をすることができることは間違いなく便利ですが、YouTubeや本では、非同期ノードの下のような状況では遅いため、正確ではない図がいくつかあります次に、小さなファイル(以下のように:85kB、170kB、255kB)の読み取りを同期します。

var fs = require('fs');

var startMeasureTime = () => {
  var start = new Date().getTime();
  return start;
};

// synch version
console.log('Start');
var start = startMeasureTime();

for (var i = 1; i<=3; i++) {
  var fileName = `Lorem-${i}.txt`;
  var fileContents = fs.readFileSync(fileName);
  console.log(`File ${1} was downloaded(${fileContents.length/1000}KB) after ${new Date().getTime() - start}ms from start.`);

  if (i === 1) {
    var hardMath = 3*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9;  
  };
};

// asynch version
setImmediate(() => {
  console.log('Start');
  var start = startMeasureTime();

  for (var i = 1; i<=3; i++) {
    var fileName = `Lorem-${i}.txt`;
    fs.readFile(fileName, {encoding: 'utf8'}, (err, fileContents) => {
      console.log(`File ${1} was downloaded(${fileContents.length/1000}KB) after ${new Date().getTime() - start}ms from start.`);
    });

    if (i === 1) {
      var hardMath = 3*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9*54/25*35/46*255/34/9;  
    };
  };
});

This is from console:
Start
File 1 was downloaded(255.024KB) after 2ms from start.
File 1 was downloaded(170.016KB) after 5ms from start.
File 1 was downloaded(85.008KB) after 6ms from start.
Start
File 1 was downloaded(255.024KB) after 10ms from start.
File 1 was downloaded(85.008KB) after 11ms from start.
File 1 was downloaded(170.016KB) after 12ms from start.
于 2017-10-26T14:23:50.103 に答える