前導文章

測試環境

  • OS: Windows 10 x64 Pro
  • CPU: Intel E3-1230v5 4C8T
  • RAM: 32GB DDR4
  • Disk: 512GB TLC SSD
  • PHP Memory Limit: 4096M

事前準備

加解密函數:

// 加密函數
function encrypt($key, $payload)
{
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv);
    return base64_encode($encrypted . '::' . $iv);
}

// 解密函數
function decrypt($key, $garble)
{
    list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
    return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}

加密用資料準備

我們用迴圈產生資料,產生的長度分別為:4kb, 16kb, 64kb, 256kb, 1mb, 4mb, 16mb 以及 64mb。 產生的方法就是很陽春的迴圈而已,並且全部都塞 a 進去,不過雖然都是同一個字元,但是與一般的檔案的隨機字元基本上沒有差異。

$str_4kb = "";
$str_16kb = "";
$str_64kb = "";
$str_256kb = "";
$str_1mb = "";
$str_4mb = "";
$str_16mb = "";
$str_64mb = "";

for($i = 0; $i < 4 * 1024; $i ++) {
    $str_4kb .= "a";
}

for($i = 0; $i < 16 * 1024; $i ++) {
    $str_16kb .= "a";
}

for($i = 0; $i < 64 * 1024; $i ++) {
    $str_64kb .= "a";
}

for($i = 0; $i < 256 * 1024; $i ++) {
    $str_256kb .= "a";
}

for($i = 0; $i < 1024 * 1024; $i ++) {
    $str_1mb .= "a";
}

for($i = 0; $i < 4 * 1024 * 1024; $i ++) {
    $str_4mb .= "a";
}

for($i = 0; $i < 16 * 1024 * 1024; $i ++) {
    $str_16mb .= "a";
}

for($i = 0; $i < 64 * 1024 * 1024; $i ++) {
    $str_64mb .= "a";

加解密時間計算

這裡也是用極為簡易的方式來測量 execution time。

$testData = array(
    "4kb" => $str_4kb,
    "16kb" => $str_16kb,
    "64kb" => $str_64kb,
    "256kb" => $str_256kb,
    "1mb" => $str_1mb,
    "4mb" => $str_4mb,
    "16mb" => $str_16mb,
    "64mb" => $str_64mb,
);

foreach ($testData as $key => $datum) {
    $time_start = microtime(true);

    $encrypted = encrypt("floatflower1029", $datum);

    $time_end = microtime(true);
    $execution_time = ($time_end - $time_start);
    echo "$key encryption: $execution_time ms\n";

    $time_start = microtime(true);

    $decrypted = decrypt("floatflower1029", $encrypted);

    $time_end = microtime(true);
    $execution_time = ($time_end - $time_start);
    echo "$key decryption: $execution_time ms\n";
}

Benchmark

資料大小加密時間解密時間
4KB77.96 ns25.03 ns
16KB57.93 ns43.86 ns
64KB193.83 ns77.01 ns
256KB459.91 ns265.12 ns
1MB3315.93 ns1955.03ns
4MB13436.08 ns10799.17 ns
16MB59468.03 ns44307.95 ns
6MKB226423.03 ns163124.08 ns

比較酷的是,16KB 的加密速度不管怎麼測都比 4KB 要來的快。

雖然沒有一個最正確的數字,但是我認為若要上傳分片加密, 大概 4 ~ 16MB 的切片最為適合,因為這樣普通小檔案就不會因為過多的切片而導致不斷開檔, 使得開檔案的時間占總 Response 時間太大部分。