gpt4 book ai didi

php - 内存:连接参数或执行 md5 哈希?

转载 作者:可可西里 更新时间:2023-10-31 23:28:48 25 4
gpt4 key购买 nike

我正在为几个函数添加内存。这些函数采用 2-3 个字符串参数(对象名称)、一个可选的 int 参数(记录 ID)和一个 bool 参数(包括已删除的记录)。每个参数组合都保证产生唯一的结果(因此值得缓存)。

我想知道连接给定的参数($param1 . $param2 . $param3 等)并将其用作数组键是否会更快,或者采用相同的连接字符串并使用 md5 哈希作为键。在 99% 的情况下,连接参数字符串的长度在 20-32 个字符之间(平均约为 27 个),而 md5 哈希始终为 32 个字符。
编辑 : 一个 md5 哈希只有 16 个字节,而不是 32 个。谢谢 Mjh。

我倾向于第一个选项,因为它:

  • 为我节省了执行 md5 哈希的成本
  • 它通常会节省几个字节的内存(平均 27 对 32 散列)(Mjh 指出这不是真的:md5 只有 16 字节),和
  • 由于 md5 哈希只是另一个字符串,因此比较较短的字符串通常会更快

  • 我怀疑这一点的唯一原因是绝大多数内存功能似乎使用 (md5) 哈希,所以我想知道我是否遗漏了什么。

    提前致谢。

    附言我忘了提:我用 # 分隔各个参数字符,它永远不会自然出现在任何参数中。

    P.P.S. 到目前为止,ankhzet 的评论似乎是最好的解决方案,因为我的字符串实际上是独一无二的: crc32($paramString) .内存占用小,校验和计算功能非常快。

    测试 crc32() 性能

    下面是一个测试脚本,它用 100 万填充 4 个数组 key => value每个配对。 values所有 4 个数组中的一个是相同的。 keys也是相同的,除了对于前 2 个数组,连接的字符串键首先具有 crc32()跑到他们身上。
    $test1Array = [];
    $start1 = microtime(true);
    for ($i = 0; $i < 1000000; $i++)
    {
    $test1Array[crc32("pagemanagement" . "#" . "staticblocktype" . "#" . $i . "#" . 1)] = "test " . $i;
    }
    $end1 = microtime(true);

    $test2Array = [];
    $start2 = microtime(true);
    for ($j = 0; $j < 1000000; $j++)
    {
    $test2Array[crc32("pagemanagement" . "#" . "staticblocktype" . "#" . $i . "#" . 1)] = "test " . $j;
    }
    $end2 = microtime(true);

    $test3Array = [];
    $start3 = microtime(true);
    for ($x = 0; $x < 1000000; $x++)
    {
    $test3Array["pagemanagement" . "#" . "staticblocktype" . "#" . $i . "#" . 1] = "test " . $x;
    }
    $end3 = microtime(true);

    $test4Array = [];
    $start4 = microtime(true);
    for ($y = 0; $y < 1000000; $y++)
    {
    $test4Array["pagemanagement" . "#" . "staticblocktype" . "#" . $i . "#" . 1] = "test " . $y;
    }
    $end4 = microtime(true);

    3 次测试运行的结果:
    测试 1:3.9902291297913
    测试 2:3.6312079429626
    测试 3:0.91605305671692
    测试 4:0.91405177116394

    测试 1:3.9842278957367
    测试 2:3.6172070503235
    测试 3:0.91405200958252
    测试 4:0.918053150177

    测试 1:3.9842278957367
    测试 2:3.6282079219818
    测试 3:0.91205215454102
    测试 4:0.91605186462402

    如果我取所有“测试 2”和“测试 4”值的平均值(因为“测试 1”似乎有初始化开销),“测试 2”为 3.6255409717560,“测试 4”为 0.9160522619883。这是 2.7094887097677 和 (2.7094887097677/1000000) = 0.0000027094887 或每次函数调用 2.72 微秒的差异。

    不幸的是,我目前无法轻松计算内存使用情况,而是存储 4 字节 crc32() value 保证比平均 27 个字符长度的字符串占用更少的内存。假设最好的情况是 1 字节字符,即每个缓存结果有 23 字节的差异。

    为了完整起见,我使用 md5() 进行了快速测试还有:
    测试 1:4.2855787277221
    测试 2:3.8108838399251
    我实际上对 md5() 之间的性能差异如此之小感到惊讶和 crc32() .当然, crc32()仍然有优势,只使用4个字节到 md5()是 16。

    结论 :由于我的函数的主要开销是在重复的数据库调用中,并且由于这些函数的调用次数约为每个请求 50-200 次,我个人认为增加的约 135-540 微秒的计算时间值得节省~1150-4600 字节的内存。

    如果有人不同意我的测试和/或结论,我很想知道。

    最佳答案

    这是我在使用 PHP7 的 AMD 2x2.3 GHz 机器上对 md5-crc32-sha1-native 散列的简单性能测试:

    function probe($label, $times, $callback) {
    $mem = memory_get_usage();
    $start = microtime(true);
    $array = $callback($times);
    $time = microtime(true) - $start;
    $mem = sprintf('%.3f', (memory_get_usage() - $mem) / 1024 / 1024);
    return "$label: $time s, $mem MB";
    }

    $times = 1000000;

    $run1 = probe('String key', $times, function ($times) {
    $a = [];
    while ($times-- > 0) {
    $a["pagemanagement" . "#" . "staticblocktype" . "#" . $times . "#" . 1] = "test " . $times;
    }
    return $a;
    });

    $run2 = probe('CRC32 key', $times, function ($times) {
    $a = [];
    while ($times-- > 0) {
    $a[crc32("pagemanagement" . "#" . "staticblocktype" . "#" . $times . "#" . 1)] = "test " . $times;
    }
    return $a;
    });

    $run3 = probe('MD5 key', $times, function ($times) {
    $a = [];
    while ($times-- > 0) {
    $a[md5("pagemanagement" . "#" . "staticblocktype" . "#" . $times . "#" . 1)] = "test " . $times;
    }
    return $a;
    });

    $run4 = probe('SHA1 key', $times, function ($times) {
    $a = [];
    while ($times-- > 0) {
    $a[sha1("pagemanagement" . "#" . "staticblocktype" . "#" . $times . "#" . 1)] = "test " . $times;
    }
    return $a;
    });

    echo join("<br/>\n", [
    $run1,
    $run2,
    $run3,
    $run4,
    ]);

    String key: 1.2421879768372 s, 111.923 MB
    CRC32 key: 1.3447260856628 s, 58.517 MB
    MD5 key: 2.1748039722443 s, 111.923 MB
    SHA1 key: 2.2480459213257 s, 119.552 MB



    看起来MD5比crc32有点slover,而crc32显然内存开销更少。

    Here您可以为 PHP5.5+-PHP7 和 hhvm 版本找到相同的测试(但迭代次数减少 x10,因为测试过程的服务器内存限制为 64MB)。

    编辑 : 添加了粗略的内存分配测试(演示链接也更新了)。看起来像 crc32在建议的测试集上占用的内存大约减少 1.5-2 倍。

    编辑 : 添加了 sha1 测试。看起来比 md5 更慢、更强大。

    注意:混洗测试顺序不会改变任何内容,因此,没有预热/内存分配会严重影响结果。

    关于php - 内存:连接参数或执行 md5 哈希?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36064690/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com