[要約&答え:明らかに問題は、乱数ジェネレータをシードするのに時間がかかることです。下の私の答えを見てください。 ]なぜscrypt()への最初の呼び出しは、わずか1%のCPUしか使用せず、GCEで30分かかりますか?
Google Compute Engine(GCE)では、Java仮想マシンアプリケーションがscryptのパスワードハッシュ関数に要する最初のリクエストは、コードがまだJust-In-Timeでコンパイルされていないため長くかかります。だから私は、 ダミーscrypt("pswd", 2,1,1)
をサーバーの起動時に呼び出すことによって、scryptをウォームアップしています。しかし、何が起こるかは、CPUが300%+に上昇し、10-20秒間そこにとどまり、scrypt()への要求がまだ完了していないにもかかわらず、1%に戻るということです。現在では、scrypt()が完了するまで、CPUは1分で数分(2GCE vCPUで30分まで)維持されます。
なぜこの奇妙な動作ですか?
なぜ終了するまで、300%のCPUでscrypt()を実行し続けないのですか?メモリが不足しているのは ではありません。下のDockerの統計を見てください。
1回目のscrypt()要求の後、後続の要求は「すぐに」終了します。たとえば、これは: SCryptUtil.scrypt("pswd", 65536, 8, 1)
はそれよりも多くの作業を行いますが、< 0.2秒かかる: SCryptUtil.scrypt("pswd", 2, 1, 1)
た(前述のように)私の非常に最初のscrypt()の呼び出しであり、通常4 GCEの仮想CPUと、数分かかります - 2GCE vCPUを使用して、通常は30分ほどかかります。
私は、4 vCPU、3.6 GB RAMを搭載したGCEインスタンスを使用しています。ドッカー1.11.1。 OpenJDK 1.8.0_77。 Alpine Linux 3.3 Dockerコンテナでは、Ubuntu 16.04 Dockerホスト。私のラップトップでこれを再現することはできません。私のラップトップでは、scryptは常に速く、ウォームアップは必要ありません。
docker stats
、5〜10秒後:(今edp_play_1のみ0.97パーセントのCPUを使用する - とのようにとどまる:
CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O BLOCK I/O PIDS
edp_nginx_1 0.02% 55.92 MB/104.9 MB 53.33% 6.191 kB/2.897 kB 0 B/0 B 6
edp_play_1 315.12% 914.7 MB/2.831 GB 32.31% 43.4 kB/66.09 kB 0 B/2.58 MB 67
edp_postgres_1 0.33% 29.84 MB/314.6 MB 9.49% 529.1 kB/307.9 kB 0 B/327.7 kB 17
edp_redis_1 0.08% 6.513 MB/52.43 MB 12.42% 4.984 kB/1.289 kB 0 B/0 B 3
docker stats
半分分後に(今edp_play_1、ライン2、300 +%のCPUを使用しています)この、半分の時間までのため、行われるまで)
CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O BLOCK I/O PIDS
edp_nginx_1 0.02% 55.92 MB/104.9 MB 53.33% 6.341 kB/3.047 kB 0 B/0 B 6
edp_play_1 0.97% 1.011 GB/2.831 GB 35.71% 130.2 kB/215.2 kB 0 B/5.546 MB 66
edp_postgres_1 0.28% 29.84 MB/314.6 MB 9.49% 678.2 kB/394.7 kB 0 B/458.8 kB 17
edp_redis_1 0.06% 6.513 MB/52.43 MB 12.42% 4.984 kB/1.289 kB 0 B/0 B 3
あなたはScalaの& SBTでテストする場合、これはGCEに私のために何が起こるかです:
scala> import com.lambdaworks.crypto.SCryptUtil
import com.lambdaworks.crypto.SCryptUtil
scala> def time[R](block: => R): R = { val t0 = System.nanoTime() ; val result = block ; val t1 = System.nanoTime() ; println("Elapsed time: " + (t1 - t0) + "ns") ; result ; }
time: [R](block: => R)R
scala> time { SCryptUtil.scrypt("dummy password 1", 2, 1, 1) }
Elapsed time: 313823ns <-- 5 minutes
res0: String = $s0$10101$2g6nrD0f5gDOTuP44f0mKg==$kqEe4TWSFXwtwGy3YgmIcqAhDvjMS89acST7cwPf/n4=
scala> time { SCryptUtil.scrypt("dummy password 1", 2, 1, 1) }
Elapsed time: 178461ns
res1: String = $s0$10101$C0iGNvfP+ywAxDS0ARoqVw==$k60w5Jpdt28PHGKT0ypByPocCyJISrq+T1XwmPlHR5w=
scala> time { SCryptUtil.scrypt("dummy password 1", 65536, 8, 1) }
Elapsed time: 130900544ns <-- 0.1 seconds
res2: String = $s0$100801$UMTfIuBRY6lO1asECmVNYg==$b8i7GABgeczVHKVssJ8c2M7Z011u0TMBtVF4VSRohKI=
scala> 313823L/1e9
res3: Double = 313.823
scala> 130900544L/1e9
res4: Double = 0.130900544
注:これはDockerとは関係ありません。私はちょうどGCEインスタンスに直接インストールされたopenjdk 8を使ってDocker外でテストしましたが、結果は同じです:scrypt(..)
は初めて3分かかるのですが、CPUは90-100%アイドルです。その後、即時に暗号化の要求が完了します。