2009-09-15 25 views
35

Trong hệ thống tôi hiện đang làm việc, có một quá trình tải lượng lớn dữ liệu vào một mảng để sắp xếp/tổng hợp/bất kỳ thứ gì. Tôi biết quá trình này cần tối ưu hóa cho việc sử dụng bộ nhớ, nhưng trong ngắn hạn nó chỉ cần làm việc.Tăng bộ nhớ PHP_limit. Tại thời điểm nào nó trở nên điên rồ?

Với lượng dữ liệu được tải vào mảng, chúng tôi tiếp tục đạt tới giới hạn bộ nhớ. Nó đã được tăng lên nhiều lần, và tôi tự hỏi có một điểm mà nó ngày càng trở thành một ý tưởng tồi? hoặc chỉ chỉ một máy tính có bao nhiêu RAM?

Máy có RAM 2GB và memory_limit hiện được đặt ở mức 1,5 GB. Chúng ta có thể dễ dàng bổ sung thêm RAM vào máy (và dù sao đi nữa).

Những người khác đã gặp phải loại sự cố này? và các giải pháp là gì?

+6

Thành thật mà nói, bạn không nên quan tâm đến việc đặt giới hạn bộ nhớ, nhưng với việc tìm ra nơi rò rỉ bộ nhớ của bạn và sửa nó. Nó không phải là một giải pháp để chỉ tăng memory_limit, nó là tránh một vấn đề trong mã. Nhìn vào các đối tượng bạn đang thiết lập và bỏ các giá trị để xóa một rò rỉ. – Petrogad

+0

Bạn có thể cụ thể về lượng dữ liệu không? Bạn có ý nghĩa gì lớn? – jergason

+8

@Frederico: OP không cố gắng sửa lỗi rò rỉ bộ nhớ, anh ấy yêu cầu giải pháp xử lý các tập dữ liệu rất lớn trong PHP. – arul

Trả lời

53

Cấu hình cho memory_limit của PHP đang chạy dưới dạng mô-đun Apache cho trang web của máy chủ phải xem xét số lượng quá trình Apache bạn có thể có cùng lúc trên máy - xem tùy chọn cấu hình MaxClients cho Apache.

Nếu MaxClients là 100 và bạn có 2.000 MB hoặc RAM, tính toán rất nhanh sẽ cho thấy bạn không nên sử dụng nhiều hơn 20 MB * (vì 20 MB * 100 khách hàng = 2 GB hoặc RAM, tức là tổng số tiền bộ nhớ máy chủ của bạn có) * cho giá trị memory_limit. Và đây không phải là xem xét rằng có lẽ những thứ khác đang chạy trên cùng một máy chủ, như MySQL, bản thân hệ thống, ... Và rằng Apache có lẽ đã sử dụng một số bộ nhớ cho chính nó.

Hoặc tất nhiên, đây cũng là "trường hợp xấu nhất", xem xét rằng mỗi trang PHP đang sử dụng số lượng bộ nhớ tối đa có thể.


Trong trường hợp của bạn, nếu bạn cần một lượng bộ nhớ lớn chỉ cho một công việc, tôi sẽ không tăng memory_limit cho PḦP chạy dưới dạng mô-đun Apache.

Thay vào đó, tôi sẽ khởi chạy công việc đó từ dòng lệnh (hoặc qua công việc cron) và chỉ định một đặc tính memory_limit cao hơn trong trường hợp một và duy nhất này.

này có thể được thực hiện với sự -d tùy chọn php, như:

$ php -d memory_limit=1GB temp.php 
string(3) "1GB" 

Xét, trong trường hợp này, temp.php rằng chỉ có chứa:

var_dump(ini_get('memory_limit')); 

Theo tôi, đây là cách an toàn hơn là tăng memory_limit cho mô-đun PHP cho Apache - và đó là những gì tôi thường làm khi tôi có một tập dữ liệu lớn, hoặc một số công cụ thực sự nặng mà tôi không thể tối ưu hóa hoặc phân trang.


Nếu bạn cần xác định một số giá trị cho việc thực hiện CLI PHP, bạn cũng có thể yêu cầu nó sử dụng tệp cấu hình khác thay vì php mặc định.ini, với -c tùy chọn:

php -c /etc/phpcli.ini temp.php 

Bằng cách đó, bạn có:

  • /etc/php.ini cho Apache, với thấp memory_limit, thấp max_execution_time ...
  • /etc/phpcli.ini cho lô chạy từ lệnh - với hầu như không có giới hạn

Điều này đảm bảo các lô của bạn sẽ có thể chạy - và bạn sẽ vẫn có bảo mật cho trang web của bạn (memory_limitmax_execution_time là biện pháp an ninh)


Tuy nhiên, nếu bạn có thời gian để tối ưu hóa kịch bản của bạn, bạn nên; ví dụ, trong tình huống đó, bạn phải đối mặt với rất nhiều dữ liệu, việc phân trang là phải có ;-)

+0

Có, giới hạn chỉ được tăng lên cho quy trình yêu cầu. Thật không may mặc dù, phân trang sẽ không giúp đỡ trong trường hợp này; kết quả cuối cùng chỉ là một số ít (20 hoặc hơn) số thống kê, nó chỉ là việc xử lý đòi hỏi không gian. –

+0

Ồ, OK ... Sau đó, tôi cho rằng nó phụ thuộc vào lượng bộ nhớ "miễn phí" của bạn khi khởi chạy quy trình đó: nếu bạn khởi chạy vào giữa đêm, khi gần như không có ai sử dụng máy chủ của bạn, có thể 1,5 GB có thể được OK (tôi sẽ sử dụng nhiều hơn, để cho một số bộ nhớ cho phần còn lại của hệ thống) - nhưng chỉ có bạn có thể nói bao nhiêu máy chủ của bạn được nạp vào thời điểm đó. –

+4

trong một số phiên bản PHP (ví dụ: PHP 5.3.15 với Suhosin-Patch) cài đặt là 1G, không phải 1GB. Kiểm tra nó hoặc PHP sẽ đặt giới hạn thành giá trị thấp nhất và tập lệnh của bạn sẽ không thực thi được, ví dụ: sử dụng 'php -d memory_limit = 1G -r" echo ini_get ('memory_limit'); "' –

2

Bạn đã thử tách tập dữ liệu thành các phần nhỏ hơn và chỉ xử lý một phần vào lúc đó?

Nếu bạn tìm nạp dữ liệu từ tệp đĩa, bạn có thể sử dụng hàm fread() để tải các khối nhỏ hơn hoặc một số sort of unbuffered db query trong trường hợp cơ sở dữ liệu.

Tôi chưa kiểm tra PHP từ v3.something, nhưng bạn cũng có thể sử dụng một dạng điện toán đám mây. Bộ dữ liệu 1GB dường như đủ lớn để được xử lý trên nhiều máy.

+0

Kế hoạch là chỉ đọc dữ liệu theo yêu cầu (như bạn đang đề xuất với fread()), nhưng đó là tái cấu trúc mà chúng ta chưa có. –

+0

Đây là câu trả lời đúng thực tế, IMNSHO: trừ khi tập dữ liệu được tương quan đầy đủ, thường có thể xử lý một phần tại một thời điểm và hiếm khi cần giữ tất cả phần đó trong bộ nhớ. Như các ghi chú OP, điều này thường đòi hỏi tái cấu trúc nontrivial. – Piskvor

1

Vì bạn biết rằng có vấn đề về bộ nhớ với tập lệnh cần sửa và bạn chỉ đang tìm giải pháp ngắn hạn, khi đó tôi sẽ không giải quyết các cách để go about profiling và giải quyết các vấn đề về bộ nhớ của bạn. Nghe có vẻ như bạn đang đi để có được điều đó.

Vì vậy, tôi sẽ nói những điều chính bạn phải ghi nhớ là:

  • Tổng bộ nhớ tải trên hệ thống
  • khả năng OS

PHP chỉ là một phần nhỏ của hệ thống. Nếu bạn cho phép nó ăn hết một lượng RAM lớn, thì các quá trình khác sẽ bị ảnh hưởng, điều này có thể ảnh hưởng đến chính kịch bản. Đáng chú ý, nếu bạn đang kéo rất nhiều dữ liệu ra khỏi cơ sở dữ liệu, thì DBMS của bạn có thể yêu cầu nhiều bộ nhớ để tạo các tập kết quả cho các truy vấn của bạn. Để khắc phục nhanh chóng, bạn có thể muốn xác định bất kỳ truy vấn nào bạn đang chạy và giải phóng kết quả càng sớm càng tốt để cung cấp cho mình nhiều bộ nhớ hơn cho một hoạt động dài.

Về khả năng của hệ điều hành, bạn nên nhớ rằng các hệ thống 32 bit, mà bạn có thể đang chạy, chỉ có thể giải quyết tối đa 4GB RAM mà không cần xử lý đặc biệt. Thường thì giới hạn có thể ít hơn nhiều tùy thuộc vào cách nó được sử dụng. Một số chipset và cấu hình Windows thực sự có thể có ít hơn 3 GB có sẵn cho hệ thống, ngay cả với 4GB hoặc cài đặt vật lý hơn. Bạn nên kiểm tra xem có bao nhiêu hệ thống của bạn có thể giải quyết.

Bạn nói rằng bạn đã tăng giới hạn bộ nhớ nhiều lần, vì vậy rõ ràng công việc này đang phát triển lớn hơn và lớn hơn trong phạm vi. Nếu bạn đang lên đến 1.5Gb, sau đó thậm chí cài đặt thêm 2Gb RAM âm thanh như nó sẽ chỉ là một reprieve ngắn.

Những người khác đã gặp phải loại sự cố này? và các giải pháp là gì?

Tôi nghĩ có thể bạn đã biết rằng giải pháp thực sự duy nhất là chia nhỏ và dành thời gian để tối ưu hóa tập lệnh sớm hoặc bạn sẽ kết thúc với một công việc quá lớn để chạy.

+0

Máy khá được dành riêng cho PHP, máy chủ cơ sở dữ liệu riêng biệt. Việc tăng giới hạn trước đó không phải vì công việc đang tăng lên (mặc dù nó sẽ, nhưng không phải là nhanh chóng), họ không đủ để "sửa" vấn đề (vì vậy chúng tôi đã thử một giới hạn lớn hơn). Bây giờ chúng ta có một giới hạn cho phép quá trình chạy, nhưng nó chắc chắn chỉ là một giải pháp ngắn hạn. Điểm tốt về giới hạn hệ thống, nó là một máy 64bit và chúng tôi sẽ tăng RAM anyway. Dù sao, tôi nghĩ rằng bạn đã trải qua nỗi sợ hãi của tôi mà ném nhiều bộ nhớ trong một quá trình duy nhất là vô lý. RDBMS làm điều đó, tại sao tôi không thể :) –

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