PHP:Linkedlist节点对象垃圾收集问题

时间:2012-02-04 16:25:48

标签: php oop garbage-collection linked-list

将第一个和最后一个节点对象标识符设置为NULL应该导致链接列表中所有节点对象的即时自动垃圾收集,因为没有对包括第一个和最后一个节点在内的所有节点对象的引用。

 $this->first = NULL
 $this->last = NULL

我们是否需要迭代整个链表并逐个取消设置每个节点对象标识符?

我认为将first和last设置为NULL就足够了,PHP代表我们在后台进行垃圾收集。

如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:3)

如果您正在运行PHP< 5.3.0并且您正在使用双向链表,则不会释放任何节点。这是因为早期的PHP版本仅使用引用计数[1],它无法识别循环引用。即使在单链表中,也可能需要通过垃圾收集器的'n'来释放整个列表,这取决于所使用的确切算法(尽管我认为这不太可能)。

进一步解释,在双向链表中,每个节点都指向该节点之前和之后的节点。考虑有序节点A,B,C。这意味着A指向,B,C指向B,B指向A和C.因此,它们的引用计数将始终为非零,除非你自己明确地取消了节点。

对于单链表,以及相同的节点A,B,C,每个节点都指向前一个节点,除了A之外,没有其他节点指向。因此,如果删除对A的引用,它将被垃圾回收。然后,由于B不再被指向,它将被释放,并在列表中继续。但是,假设垃圾收集器以反向或随机顺序访问列表(而不是从左到右最佳)。然后,它可以先看B,然后结束A仍然指向它,因此不需要释放。然后GC释放A并完成。虽然,GC算法更有可能在没有更多要收集的情况下继续收集零引用计数的内存,这样可以避免这个问题。

值得庆幸的是,从PHP 5.3.0开始,我们不必担心循环引用[2]。该算法通过从根存储器节点构造树来工作。最终树中未包含的任何内容都必须是孤立的(因此仅因为循环引用而保持活动状态),因此可以释放。所以,是的,只要程序中没有任何其他内容指向列表中的任何节点,就可以通过删除对开头和结尾的引用来释放整个列表。

请注意,释放孤立循环引用的算法比简单引用计数更昂贵。显式释放代码可能有益也可能无益。必须仔细进行基准测试才能找到它。

答案 1 :(得分:2)

有时我遇到PHP垃圾收集过程的问题。

你可以在链接列表的实现中解决这个问题。

  • 每次创建数据结构时,将其创建为函数中的局部变量, 不全球化。稍后,在代码的其他部分分配,您将在其中使用它。 如果直接指定变量,则可能有相同参考的副本, 而不是具有相同数据的新结构。

  • 我建议将“List”结构实现为独立结构, 不仅是指向第一个或最后一个节点的指针

  • 在链接列表的情况下,我添加了2个特殊节点,就像你的“第一个”& “持续”, 它不存储任何数据,并且永远不会删除,除非整个链表, 将被删除。当列表为空时,它们相互链接, 当添加真实数据节点时,它们将被设置在这些节点之间。

  • 当您删除第一个节点时,不会删除特殊的“第一个”节点标记,而是特殊“第一个”标记之后的节点。< / p>

  • 删除最后一个节点时,不会删除特殊的“最后”节点标记,而是特殊“最后”标记之前的节点。< / p>

建议:

<?php

/* listitem */ function newitem($data)
{
    // executing a function that returns
    // a local variable,
    // forces php to create a new item, each time,
    // instead of making a copy,
    // that conflicts with garbage collection

    /* listitem var */ $Result = array(
      "data"  => $data,
      "prev"  => null,
      "next"  => null,
    );

    return $Result;
} // listitem function newitem(...)

/* linkedlist */ function newlist()
{
    // executing a function that returns
    // a local variable,
    // forces php to create a new item, each time,
    // instead of making a copy,
    // that conflicts with garbage collection

    /* linkedlist var */ $Result = array(
      "start" => newitem();   // <- "marker" for start of list, don't store data here
      "finish" => newitem();  // <- "marker" for end of list, don't store data here
    )

    return $Result;
} // linkedlist function newlist(...)

/* void */ function linkitem(&$before, &after)
{
  if (($before != null) && ($after != null))
  {
    "start" <=> "item"
    $before["next"] = $after; 
    $after["prev"]  = $before; 
  }
} // void function linkitem(...)

/* void */ function additem(&$list, &item)
{
  if ($item != null)
  {
    "start" <=> "item"
    linkitem(/* & */ $list["start"], /* & */ $item); 
    "item" <=> "finish"
    linkitem(/* & */ $item, /* & */ $list["start"]); 
  }
} // void function additem(...)

/* void */ function example()
{
  /* linkedlist var */ $SolarSystem = newlist();

  /* listitem var */ $item = null;

  $item = newitem("Sun");
  // check for reference parameters
  additem( /* & */ $SolarSystem, /* & */ $item);

  $item = newitem("Mercury");
  additem( /* & */ $SolarSystem, /* & */ $item);

  $item = newitem("Venus");
  additem( /* & */ $SolarSystem, /* & */ $item);

  // ...

} // void function example(...)

?>

视觉表现可能是这样的:

.............................................................
....+-------------------+....................................
....|    SolarSystem    |....................................
....+---------+---------+....................................
..............|..............................................
..............v..............................................
....+---------+---------+...........null.....................
....|  Last   |  First  |............^.......................
....+---+-----+----+----+............|.......................
........|..........|.........+-------+-+.....................
........|..........+-------->|  prev   |.....................
........|....................+---------+....+-----------+....
........|....................|  data   +--->|   "Sun"   |....
........|....................+---------+....+-----------+....
........|....................|  next   |.....................
........|....................+-+-------+.....................
........|......................|.....^.......................
........|......................v.....|.......................
........|....................+-------+-+.....................
........|....................|  prev   |.....................
........|....................+---------+....+-----------+....
........|....................|  data   +--->| "Mercury" |....
........|....................+---------+....+-----------+....
........|....................|  next   |.....................
........|....................+-+-------+.....................
........|......................|.....^.......................
........|......................v.....|.......................
........|....................+-------+-+.....................
........|....................|  prev   |.....................
........|....................+---------+....+-----------+....
........+------------------->|  data   |--->|  "Venus"  |....
.............................+---------+....+-----------+....
.............................|  next   |.....................
.............................+-+-------+.....................
...............................|.............................
...............................v.............................
..............................null...........................
.............................................................

干杯。