teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

追記

2020/05/22 22:14

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -51,4 +51,35 @@
51
51
  ※コード内にある console.time() 〜 console.timeEnd() は 2. において追加しました。
52
52
  非同期であるため意味のないコード(処理開始された時点での反応速度)であり、実際は数分の時間を要しました。
53
53
 
54
- ![RaspberryPi3B+](9b90b12db56b1b84952a0fa22ecdbe99.png)
54
+ ![RaspberryPi3B+](9b90b12db56b1b84952a0fa22ecdbe99.png)
55
+
56
+ ## 子プロセスを起動してコマンドラインを叩く方法
57
+
58
+ 本題の fs からは離れますが、[child_process](https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback) で ``cp`` コマンドも試しました。
59
+ バイナリアプリケーションに委譲するのでメモリ管理は不要との考えです
60
+
61
+ ```javascript
62
+ const {exec} = require('child_process');
63
+
64
+ let cpCommand = ( file1, file2 ) => `cp ${file1} ${file2}`;
65
+
66
+ let start = Date.now();
67
+ exec(cpCommand("test.txt", "test2.txt"), (error, stdout, stderr) => {
68
+ if (error) {
69
+ console.error(`exec error: ${error}`);
70
+ return;
71
+ }
72
+ console.log(`time: ${Date.now()-start} [msec]`);
73
+ console.log(`stdout: ${stdout}`);
74
+ console.error(`stderr: ${stderr}`);
75
+ });
76
+ // time: 208008 [msec]
77
+ // stdout:
78
+ // stderr:
79
+ ```
80
+ SDカードから読み、同一SDカードに複製するのに約5分かかりました。
81
+ microSDHC-I での複製は1分あたり500MBが目安かもしれません。
82
+ SSDドライブを利用するなど、ハードウェア性能を向上させる方法はあると思いますが、試していません
83
+
84
+ RaspberryPi は普通のLinuxマシンではありますが、ハードウェア性能は低いので、取り扱うファイルはサイズ上限を定めてシステム構築/運用するのが良いかもしれません。
85
+ 500MBを超えると、正直、辛いと思います

2

試験結果画像の掲載

2020/05/22 22:14

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -40,4 +40,15 @@
40
40
  }
41
41
  }
42
42
 
43
- ```
43
+ ```
44
+
45
+ #実機試験試験結果:
46
+
47
+ 手元の RaspberryPi3B+ で実験しました。
48
+
49
+ 1. ご質問のコード(エラーで停止)
50
+ 2. 回答させていただいた pipe() の方法(コピー成功)
51
+ ※コード内にある console.time() 〜 console.timeEnd() は 2. において追加しました。
52
+ 非同期であるため意味のないコード(処理開始された時点での反応速度)であり、実際は数分の時間を要しました。
53
+
54
+ ![RaspberryPi3B+](9b90b12db56b1b84952a0fa22ecdbe99.png)

1

追記

2020/05/22 10:08

投稿

AkitoshiManabe
AkitoshiManabe

スコア5434

answer CHANGED
@@ -6,4 +6,38 @@
6
6
 
7
7
  * qiita [2016年版 Node.jsで幸せになれる10の習慣](https://qiita.com/ksato9700/items/b21383e613b6dc308dca) の「7.ゴミを避けろ」セクション
8
8
  * [0から始めるNode.jsパフォーマンスチューニング](https://blog.koh.dev/2020-03-04-nodejs-performance/)
9
- * etc
9
+ * etc
10
+
11
+ ----
12
+
13
+ 追記)
14
+ NodeJS のソースコードまで確認できていませんが、fs.copyFileSync() は、扱うファイルサイズに応じたメモリ領域を要するのかもしれません。
15
+
16
+ Stream レベルでのコピーも試してみてください。
17
+ 時間はかかるかもしれませんが、限られたメモリサイズを用いてコピーするはずです。
18
+
19
+ ```javascript
20
+ var fs = require("fs");
21
+
22
+ // 1. .pipe() で chunk データを渡す方法(今回のご質問内容ですと、こちらが手軽)。
23
+ fs.createReadStream('src.txt').pipe(fs.createWriteStream('dest.txt'));
24
+
25
+ // 2. 昔、書いた愚直にイベントリスナでコピーする方法(1.と同じ様なことをやっています)
26
+ var copyFile = ( srcFile, dstFile, callback ) => {
27
+ var stat = fs.statSync( srcFile ), newFile, oldFile;
28
+ if( fs.existsSync( srcFile ) && stat.isFile() ) {
29
+ newFile = fs.createWriteStream( dstFile ); // to
30
+ oldFile = fs.createReadStream( srcFile ); // from
31
+ oldFile.addListener("data", (chunk) => {
32
+ newFile.write(chunk);
33
+ });
34
+ oldFile.addListener("close",() => {
35
+ newFile.end();
36
+ if(callback) {
37
+ callback();
38
+ }
39
+ });
40
+ }
41
+ }
42
+
43
+ ```