2010-06-24 46 views
13

Tôi có một tập lệnh PHP chạy trên cron có thể mất tối đa 15 phút để thực thi. Trong khoảng thời gian thường xuyên tôi có nó phun ra memory_get_usage() vì vậy tôi có thể nhìn thấy những gì đang xảy ra. Lần đầu tiên nó cho tôi biết cách sử dụng của tôi là 10 meg. Khi kịch bản kết thúc tôi ở 114 megs!Thu thập rác php trong khi tập lệnh chạy

PHP có thực hiện thu thập rác trong khi tập lệnh đang chạy không? Hay điều gì đang xảy ra với tất cả ký ức đó? Có điều gì tôi có thể làm để ép buộc thu gom rác hay không. Nhiệm vụ mà kịch bản của tôi đang thực hiện là nhập khẩu hàng nghìn nghìn nút vào Drupal. Vì vậy, nó đang làm điều tương tự rất nhiều lần.

Mọi đề xuất?

Trả lời

16

Điều quan trọng là bạn unset biến toàn cầu của bạn ngay khi bạn không cần chúng.

Bạn không cần gọi không được đặt rõ ràng cho các biến cục bộ và thuộc tính đối tượng vì chúng bị hủy khi hàm vượt quá phạm vi hoặc đối tượng bị hủy.

PHP giữ số tham chiếu cho tất cả các biến và phá hủy chúng (trong hầu hết các điều kiện) ngay sau khi số tham chiếu này chuyển thành 0. Các đối tượng có một số tham chiếu nội bộ và các biến tự (tham chiếu đối tượng) mỗi đối tượng có một số tham chiếu. Khi tất cả các tham chiếu đối tượng đã bị hủy bởi vì các tham chiếu của chúng có thể đạt 0, chính đối tượng đó sẽ bị hủy. Ví dụ:

$a = new stdclass; //$a zval refcount 1, object refcount 1 
$b = $a;   //$a/$b zval refcount 2, object refcount 1 
//this forces the zval separation because $b isn't part of the reference set: 
$c = &$a;   //$a/$c zval refcount 2 (isref), $b 1, object refcount 2 
unset($c);   //$a zval refcount 1, $b 1, object refcount 2 
unset($a);   //$b refcount 1, object refcount 1 
unset($b);   //everything is destroyed 

Nhưng xem xét kịch bản sau đây:

class A { 
    public $b; 
} 
class B { 
    public $a; 
} 

$a = new A; 
$b = new B; 
$a->b = $b; 
$b->a = $a; 
unset($a); //cannot destroy object $a because $b still references it 
unset($b); //cannot destroy object $b because $a still references it 

Những tài liệu tham khảo cyclic là nơi PHP 5.3 của đá thu gom rác trong Bạn có thể gọi một cách rõ ràng thu gom rác với gc_collect_cycles..

Xem thêm Reference Counting BasicsCollecting Cycles trong hướng dẫn.

2

Sử dụng unset() càng nhiều càng tốt, kiểm tra bộ nhớ đã sử dụng thường xuyên hơn. có, php không thu gom rác thải trong thời gian chạy trên một vài điều kiện. đây là một số hữu ích post trên php.net.

1

Nếu bộ nhớ tăng nhiều, thì có thể bạn không phát hành bộ nhớ. Bạn đã tạo ra một rò rỉ bộ nhớ. Bộ sưu tập rác sẽ không giúp bạn nếu bạn không bỏ đặt biến, phá hủy các đối tượng và/hoặc chúng vượt ra khỏi phạm vi.

Bạn có tắt các nút bạn tải sau khi bạn đã hoàn tất chúng không? Tôi đã viết kịch bản PHP chạy hàng giờ, xử lý hàng triệu bản ghi cơ sở dữ liệu, không có vấn đề gì và sử dụng bộ nhớ đi lên và xuống trong phạm vi rất chấp nhận được.

3

PHP garbage collection phần lớn là bộ đếm tham chiếu (nó có một số phát hiện chu kỳ.) Nếu bạn đang giữ tài liệu tham khảo mà vẫn có thể truy cập xung quanh chúng sẽ dễ dàng thêm nếu không được giải phóng.

Sử dụng unset() để biến miễn phí bạn không còn sử dụng nữa. Nếu bạn chỉ đơn giản ghi đè lên các biến (ví dụ, bằng null), điều này sẽ chỉ cho phép GC giảm bớt lượng không gian được yêu cầu bởi biến đó, nhưng không nhiều như bỏ đặt mà thực sự cho phép hủy bỏ giá trị tham chiếu.

Bạn cũng nên phát hành đúng bất kỳ tài nguyên nào mà bạn sử dụng.

Bạn sẽ vẫn thấy tăng bộ nhớ trong thời gian chạy vì GC được tự do giải phóng nó theo cách riêng của nó, chẳng hạn như khi có chu kỳ CPU miễn phí hoặc khi nó bắt đầu cạn bộ nhớ.

Các vấn đề liên quan