PHP中,如果创建新数组或将相同索引添加到现有数组中,内存使用情况是否存在显著差异?

3
如果我创建一个包含几百个索引的数组,相对于将第二维度添加到现有数组中,需要多少额外开销?
例如,$pages['page']['url'] 和 $titles['page']['title'] 相对于 $pages['page']['url']['title'] 和 $pages['page']['title'],其中最后一个示例假定 $pages 的每个索引都包含一个关联数组。
目标是查找每个“页面”的两个属性。每个“页面”都有一个“url”和一个“标题”,哪种方法在数组的内存使用效率上更高?哪种方法在访问/存储数据上更高效?
两个关联数组:
// Store the information in arrays
$titles['page1'] = 'Page 1 Title';
$titles['page2'] = 'Page 2 Title';

$urls['page1'] = 'http://www.page1.com';
$urls['page2'] = 'http://www.page2.com';

// Display an example
echo $titles['page1'] . ' is at ' . $urls['page1']; 

或者一个包含数组的数组:
$pages['page1'] = array( 'title' => 'Page 1 Title', 'url' => 'http://www.page1.com' );
$pages['page2'] = array( 'title' => 'Page 2 Title', 'url' => 'http://www.page2.com' );

// Display an example
echo $pages['page1']['title'] . ' is at ' . $pages['page1']['url'];

1
你能解释一下上下文吗?为什么不保留一个包含页面所有信息的页面对象,并将页面索引在一个单独的数组中? - JackWink
你对数组结构差异的解释太不精确了。一个新数组至少占用200个字节。仅添加一个新键不会占用太多空间。但在你的情况下,似乎是添加了一个新的子数组。在这种情况下,它并不重要。子数组和单独的数组变量占用相同的空间。 - mario
2
你可能想考虑创建一个页面对象,这样你就可以创建任意数量的属性,而不是创建3层多维数组,这样最终你只会得到一个页面对象数组。我相信这也会减少你的内存占用。 - Mike Purcell
@DigitalPrecision 我事后想到了这一点,如果我再做一次的话,我会按照你的建议去做。不知为何,我在 PHP 中从来没有考虑过对象。 - Marshall Davis
@ToothlessRebel 你有没有看过我的更新答案?我认为现在这个回答解决了你的问题,如果我理解错了,请解释一下。 - Smamatti
显示剩余3条评论
4个回答

0

二维数组的内存使用略微更大,但这可能是由于糟糕的代码所导致的(?)。

<!--
    http://php.net/manual/en/function.memory-get-usage.php

    array1: 116408 (1D 1001 keys)     (1x 100.000 keys:  11.724.512)
    array2: 116552 (2D, 1002 keys)    (2x  50.000 keys:  11.724.768)

    total:    +144                                             +256
-->

<?php

function genRandomString() {
    $length = 10;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
    $string = '';    

    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters))];
    }

    return $string;
}

$i = 0;

// ----- Larger 1D array -----
$mem_start = memory_get_usage();
echo "initial1: " . $mem_start . "<br />";
$arr = array();

for ($i = 1; $i <= 1000; $i++) {
    $arr[ genRandomString() ] = "Hello world!";
}

echo "array1: " . (memory_get_usage() - $mem_start) . "<br />";
unset($arr);

// ----- 2D array -----
$mem_start = memory_get_usage();
$arr2 = array();

echo "initial2: " . $mem_start . "<br />"; 


for ($i = 1; $i <= 500; $i++) {
    $arr2["key______1"][ genRandomString() ] = "Hello world!";
    $arr2["key______2"][ genRandomString() ] = "Hello world!";
}

echo "array2: " . (memory_get_usage() - $mem_start) . "<br />";

unset($arr2);

unset($i);
unset($mem_start)    
echo "final: " . memory_get_usage() . "<br />"; 

?>

@ToothlessRebel,我的回答是基于值的。抱歉,我没有仔细阅读。我现在已经修正了我的答案。它现在基于键。 - Smamatti

0
一个数组比两个数组占用更少的内存:
 total mem two arrays: 2496
 total mem one array: 1848

我在编程中做计算,将'aaaa'分配给一个和两个数组中的每个元素,同时捕获memory_get_usage()

编辑: 更正:如果其中一个是一级数组,则使用两个数组比使用一个数组更好。

添加了代码。我修改了它,将更多的元素放入数组,并仅使用一个级别的数组:


两个数组的总内存:1,009,720

一个数组的总内存:1,011,112

$memI = memory_get_usage();

for ($i = 0; $i < 1000; $i++)
{
     $pages[uniqid()][uniqid()] = 'aaaa';
     $titles[uniqid()] = 'aaaa';
}

$memF = memory_get_usage();

$memCalc = $memF - $memI;

echo "<pre>total mem two arrays: " . number_format($memCalc);


unset($pages);
unset($titles);

$memI = memory_get_usage();

for ($i = 0; $i < 1000; $i++)
{
    $pages['page'][uniqid()][uniqid()]  = 'aaaa';
    $pages['title'][uniqid()] = 'aaaa';
}

$memF = memory_get_usage();

$memCalc = $memF - $memI;

echo "<pre>total mem one array: " . number_format($memCalc);

你确定你没有在两个数组中使用了两倍数量的元素(每个数组中数量相同)吗?请检查我的答案。谢谢! - Smamatti
是的 @Smamatti,我确定,问题不在于多级数组是否比两个一级数组占用更多内存,问题在于多级数组是否比两个多级数组占用更多内存,在问题中间请注意例如部分。在这种情况下,一个复杂的多级数组比两个简单的多级数组占用更少的内存。 - corretge
更正:如果其中一个是一级数组,那么使用两个数组比使用一个更好。谢谢。 - corretge

0

我认为多维数组与几个数组之间的差异在内存使用方面并不大,但字符串和整数在内存方面确实有很大的区别。

将编码规范应用于编程可以使用更少的内存。

以此示例为例:

$pages['page1'] = array( 'title' => 'Page 1 Title', 'url' => 'http://www.page1.com' );
$pages['page2'] = array( 'title' => 'Page 2 Title', 'url' => 'http://www.page2.com' );

// Display an example
echo $pages['page1']['title'] . ' is at ' . $pages['page1']['url'];

你可以重新编写它:

$pages[] = array('Page 1 Title','www.page1.com' );
$pages[] = array('Page 2 Title','www.page2.com' );

// Display an example
foreach ($pages as $page){
   echo $page[0] . ' is at http://' . $page[1];
}

你也可以使用键的定义来实现自我记录代码的想法:

define("TITLE_KEY", 0);
define("URL_KEY", 1);
$pages[] = array(TITLE_KEY=>'Page 1 Title',URL_KEY=>'www.page1.com' );
$pages[] = array(TITLE_KEY=>'Page 2 Title',URL_KEY=>'www.page2.com' );

// Display an example
foreach ($pages as $page){
   echo $page[TITLE_KEY] . ' is at http://' . $page[URL_KEY];
}

-1

PHP并没有真正的数组。PHP技术上有一个映射,有时也称为关联数组。映射速度取决于元素数量,当您添加元素时,内存使用量不会影响时间。


这个问题似乎集中在基于数据结构的内存使用上。因此,时间不是问题,但需要额外的引用。可能会有性能差异,因为二维数组可能需要另一个查找(根据PHP内部实现方式而定)。 - Smamatti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接