2013-05-14 34 views
5

Các tài liệu PHP có điều này để nói về pg_free_result():Có cần pg_free_result(), ngay cả khi kết quả nằm ngoài phạm vi?

Chức năng này chỉ cần được gọi là nếu tiêu thụ bộ nhớ trong kịch bản thực hiện là một vấn đề. Nếu không, tất cả bộ nhớ kết quả sẽ là sẽ tự động được giải phóng khi tập lệnh kết thúc.

http://www.php.net/manual/en/function.pg-free-result.php

tôi sẽ (có lẽ ngây thơ) đã dự kiến ​​các nguồn lực được trả về bởi một cuộc gọi đến pg_query() để được thu gom rác khi nó đi ra khỏi phạm vi.

Trong một hàm giả thuyết như thế này:

function selectSomething() 
{ 
    $res = pg_query("SELECT blah FROM sometable"); 
    // do something with $res 
    pg_free_result($res); // required or not? 
} 

Là nó thực sự cần thiết để gọi pg_free_result() ở cuối?

Nói cách khác, nếu tôi gọi hàm này 1000 lần, nó sẽ ăn bộ nhớ để lưu trữ tất cả 1000 kết quả?

EDIT: Tôi đang nói về trường hợp điển hình, tức là pg_connect() thay vì pg_pconnect().

+0

Tùy thuộc, bạn có đang buộc kết nối pg mới hay kết nối liên tục không? Nếu bạn đang sử dụng kết nối liên tục, [tài nguyên có thể không phải là GC'ed] (http://www.php.net/manual/en/language.types.resource.php). Nhưng tại sao không hồ sơ kịch bản.Viết một ít test-case và kiểm tra việc sử dụng bộ nhớ. Nếu nó tiếp tục tăng cho đến khi kết thúc tập lệnh, hãy thêm 'pg_free_result' và chạy lại ... –

+0

Đây là câu hỏi chung hơn, bất kể loại kết nối. Tôi biết tôi chỉ có thể viết một bài kiểm tra, nhưng nó làm phiền tôi rằng tài liệu đó rất mơ hồ. Thử nghiệm một lần sẽ chỉ trả lời câu hỏi của tôi cho một nền tảng và phiên bản cụ thể (PHP và/hoặc libpq). – Zilk

+0

Thực ra, bạn đã có một điểm tốt ở đó. Tôi đã chỉnh sửa câu hỏi để nói rằng tôi đang nói về 'pg_connect()'. – Zilk

Trả lời

0

Dưới đây là kết quả xét nghiệm của tôi:

(trước/sau)

với: 631288/631384

không: 631288/631640

Hãy chạy thử nghiệm bản thân với điều này mã:

<?php 
class test { 
    private static $tests = 5000; 

    public function __construct() { 
     $dbconn = pg_connect("host=### dbname=### user=### password=###") 
      or die('Could not connect: ' . pg_last_error()); 

     self::test(self::$tests, true); 
     self::test(self::$tests, false); 
    } 

    private function test($times, $with) { 
     echo ($with ? "with:<br />\n" : "without:<br />\n") . memory_get_usage() ."<br />\n"; 

     for($i = 0; $i < $times; $i++) { 
      $res = pg_query("SELECT * FROM chowder"); 

      if($with) { 
       pg_free_result($res); 
      } 
     } 

     echo memory_get_usage() ."<br /><br />\n\n"; 
    } 

} 

$test = new test(); 
+0

Tôi không thể sao chép kết quả của bạn cho trường hợp sử dụng được đề cập trong câu hỏi. Nhìn vào đây: http://pastebin.com/ghw1PHuE – Zilk

+0

Nhân tiện, kiểm tra của bạn ảnh hưởng trực tiếp đến việc sử dụng bộ nhớ bằng cách thêm các khóa và giá trị vào $ memory_usage. Loại bỏ chúng, và bạn nhận được kết quả tương tự cho có/không có (cộng trừ một vài byte). – Zilk

+0

Ah vâng tôi đã đoán nó sẽ quảng cáo một lượng không đáng kể bằng cách sử dụng mảng. Tôi đã cập nhật bài kiểm tra và kết quả của mình. –

1

Vì Elias Van Ootegem đúng cho biết bạn gần như chắc chắn sử dụng kết nối liên tục. Với các kết nối liên tục sau khi truy vấn kết quả phải tiếp tục trong bộ nhớ vì bạn có thể muốn thu thập thêm dữ liệu từ nó (ví dụ như lỗi cuối cùng).

Vì vậy, thực hành tốt. Nếu bạn đang hoạt động trong một môi trường mà bạn có 2M bộ nhớ có sẵn và kịch bản của bạn có thể, đôi khi, đạt tới 0,1M bộ nhớ thì giới hạn trên là 20 kết nối đồng thời gọi tập lệnh đó. Sau đó các yêu cầu web tiếp theo sẽ xếp hàng hoặc thả. Nó không có một thiên tài để nhận ra mức độ dễ bị tấn công của DDoS.

Thực tiễn tốt nhất là bộ nhớ trống ngay khi bạn hoàn thành. Điều này đi cho bất kỳ chương trình hay kịch bản nào. Khi hệ thống đang được nhấn mạnh và nhu cầu cao thì càng có nhiều yêu cầu có thể được phục vụ bên trong phạm vi toàn bộ bộ nhớ thì càng tốt. Nếu bạn có thể giảm dung lượng bộ nhớ tối đa của một tập lệnh, bạn có thể tăng số lượng kết nối đồng thời có thể hợp lý để gọi nó và do đó tăng tải tập lệnh có thể xử lý.

Cách lý tưởng để làm mọi thứ là giải phóng tài nguyên ngay khi có thể. Chỉ vì chúng tôi không và mọi thứ dường như hoạt động trong quá trình thử nghiệm là không có lý do gì để không làm.

+0

Tôi đã nhận xét về điều này trong câu trả lời của Elias, nhưng câu trả lời đó đã bị xóa cùng với các bình luận. Tóm lại: không, đây chắc chắn không phải là kết nối liên tục. Không sử dụng tham số $ conn trong pg_query chỉ ngầm sử dụng kết nối cuối cùng được mở bởi 'pg_connect()' (hoặc 'pg_pconnect()'). Kết nối liên tục là một thứ hoàn toàn khác. Trong số những thứ khác, chúng sẽ giữ các khóa và các giao dịch hoạt động giữa các yêu cầu HTTP (nếu mod_php được sử dụng), hầu như luôn không mong muốn. Chúng tôi đang sử dụng PgBouncer như một pooler kết nối để thay thế. – Zilk

+0

Đối với các phương pháp hay nhất, PHP sử dụng bộ sưu tập rác, thường làm cho nó không cần thiết đối với các tài nguyên() miễn phí một cách rõ ràng. Chúng sẽ được đánh dấu để thu thập rác khi chúng không thể truy cập được (tức là khi chúng không nằm trong phạm vi). Thực hành tốt nhất trong các ngôn ngữ thu gom rác thải là để cho GC làm việc của nó. Câu hỏi đặt ra là nếu điều đó cũng áp dụng cho các tài nguyên kết quả PG, _do_ có một hàm free(), và từ bài kiểm tra mà tôi đã đăng dưới dạng bình luận cho câu trả lời của Joel, có vẻ như nó đã xuất hiện. Nhưng đó chỉ là một thử nghiệm, chứ không phải là hành vi được tài liệu chính thức. – Zilk

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