Khách hàng Magento lưu rò rỉ bộ nhớ


7

Tôi đang cố gắng chỉnh sửa hàng loạt dữ liệu khách hàng (một vài nghìn bản ghi) và Magento tiếp tục hết bộ nhớ khả dụng để chạy tập lệnh.

Sau một số thử nghiệm với memory_get_usage()thủ phạm dường như là $customer->save()phương pháp dường như chiếm 5M bộ nhớ cho mỗi lần lưu nhưng không giải phóng nó khi hoàn tất.

Kết quả là, khi lặp qua vài nghìn bản ghi, nó đang chạy bộ nhớ.

Đây là những gì tôi đã thử cho đến nay:

$customer->clearInstance()

unset($customer)

Điều này dường như không giúp đỡ mặc dù.

Dưới đây là mã của tôi:

public function createCustomerAddress($customerAddressData, $email){
     $customer = Mage::getModel('customer/customer');

     $customer->setWebsiteId(Mage::app()->getWebsite()->getId());
     $customer->loadByEmail($email);

     $address   = Mage::getModel('customer/address');

     $address->addData($customerAddressData);
     $customer->addAddress($address);
     unset($address);
     try{
         $customer->save();
     }catch (Exception $e){
         var_dump($customerAddressData);
         var_dump($e->getMessage());
     }
    echo "\n" . "Before unsetting \n" . memory_get_usage() . "\n";
    $customer->clearInstance();
    unset($customer);
    echo "\n" . "After  \n" . memory_get_usage() . "\n";  // no difference than before
}

Mọi sự trợ giúp sẽ rất được trân trọng.

ps Tôi không chắc clearInstance()chức năng (trong Mage_Core_Model_Ab bát) có làm gì không, nếu ai đó có cái nhìn sâu sắc về điều này, nó sẽ được đánh giá rất cao nếu được chia sẻ :)


Phiên bản Magento nào bạn đang sử dụng?
jesseconnr

Magento CE 1.7.0.2, nhưng cũng đang thử nghiệm nó trên cùng một vấn đề Magento EE
pzirkind

1
Thay vì các cách giải quyết được cung cấp dưới dạng câu trả lời, có thể theo dõi rò rỉ bộ nhớ thực tế nếu bạn có thời gian. Xin vui lòng xem hai bài viết tôi cung cấp. Cái đầu tiên có thể giúp bạn theo dõi vấn đề, cái thứ hai giải thích một lỗi trong chính PHP. Có thể vấn đề tương tự cũng xuất hiện ở Magento. stackoverflow.com/questions/849549/ Nam paul-m-jones.com/archives/262
jesseconnr

bạn đang sử dụng phiên bản php nào?
Flyingmana

@Fellingmana 5.4.17 trên máy dev và 5.3 khi sản xuất
pzirkind 13/03 '

Câu trả lời:


3

Tôi nghĩ rằng điều này có liên quan đến một vấn đề cốt lõi của PHP, vấn đề không dễ giải quyết nếu không sửa đổi nhiều cho các tệp Magento cốt lõi.

Cách duy nhất để thực hiện điều này là sử dụng một cách giải quyết:

Tôi đề nghị:

a. Nếu điều này được gọi từ trình duyệt, tôi sẽ thực hiện một cuộc gọi ajax riêng, như @Julien Lacal khuyến nghị trong câu trả lời của anh ấy.

b. Nếu tất cả đã được thực hiện phía máy chủ, tôi sẽ chia nó thành hai tập lệnh, với 1. tập lệnh lặp lại danh sách khách hàng hiện có và 2. tập lệnh gọi createCustomerAddresshàm, sử dụng thông số bài. Tập lệnh thứ hai sau đó sẽ được gọi bằng cách sử dụng CURL từ tập lệnh đầu tiên, sao cho mỗi phiên bản của tập lệnh thứ hai chạy riêng rẽ và không bị ảnh hưởng bởi rò rỉ bộ nhớ.


5

Bộ nhớ chỉ được giải phóng khi không có tham chiếu đến biến / đối tượng đó. Tôi nghi ngờ - và sẽ chỉnh sửa câu trả lời của tôi sau khi được xác nhận, rằng hệ thống sự kiện trong Magento chuyển một thể hiện của mô hình cho người quan sát, và do đó có một tham chiếu đến nó trong bộ nhớ.

Nhưng đây là một vấn đề được ghi chép lại. (một cái mà tôi đã nhận xét vào năm 2011 http: //www.magentoc Commerce.com/boards/viewthread/26561/ ).


Chắc chắn có ý nghĩa, tuy nhiên người quan sát nên phát hành nó vào một lúc nào đó
pzirkind

afaik không có trình thu gom rác php tiêu chuẩn KHÔNG tìm thấy các vòng tròn, do đó, có thể là, nếu bạn có một khách hàng và một địa chỉ, cả hai đối tượng đều không được giải phóng - chỉ là một ý tưởng, cảm ơn vì câu trả lời joseph!
Fabian Blechschmidt

Âm thanh hợp lý - trong nháy mắt chỉ có mô-đun bản tin dường như quan sát sự kiện lưu khách hàng. @pzirkind Bạn có thấy mức tiêu thụ bộ nhớ tương tự với phần mở rộng bản tin bị vô hiệu hóa hoàn toàn không?
Kristof tại Fooman

@Fooman vâng, nó dường như có cùng mức tiêu thụ bộ nhớ khi mô-đun bản tin bị vô hiệu hóa (thông qua xml)
pzirkind

4

Tôi tin rằng đây là sự cố đã biết trên tất cả các nền tảng và phiên bản của Magento. unset()hoặc clearInstance()sẽ không có tác dụng. Mage::getModel()bộ nhớ bị rò rỉ trong tất cả các trường hợp tôi gặp (khách hàng, sản phẩm, đơn đặt hàng, v.v.). Cách duy nhất mà tôi đã tìm thấy là sử dụng một bộ sưu tập thay thế, nếu có thể (có thể không áp dụng cho bạn), khi xử lý một số lượng lớn các sáng tạo đối tượng. Khi quá trình của bạn hoàn tất, bộ nhớ sẽ được giải phóng.

Bạn đang hết bộ nhớ? Điều này thường không phải là một vấn đề trừ khi bạn là. Nếu bạn sắp hết bộ nhớ, có lẽ, bạn có thể thử chia quy trình hàng loạt thành các lần chạy riêng biệt trong tiện ích mở rộng của mình. Nếu đây là một kịch bản shell, thì nó sẽ dễ dàng phá vỡ nó. Chỉ cần tạo hai hoặc nhiều tệp và chạy từng tệp một với các phạm vi khách hàng được xác định trước entity_id.


Cảm ơn thông tin sẽ xem xét sử dụng các bộ sưu tập cho việc này, đã tự hỏi liệu có một số loại sửa chữa có sẵn cho rò rỉ mô hình hay không
pzirkind

đã thử lưu một bộ sưu tập bằng cách sử dụng $ Collection-> save () và dường như bị rò rỉ bộ nhớ tương tự, có một số mã bạn có thể đăng ở đó tôi có thể thấy sự khác biệt trong bộ nhớ không?
pzirkind

2

Một cách giải quyết tốt sẽ là xây dựng mô-đun quản trị của riêng bạn để nhập số lượng lớn khách hàng và sử dụng các lệnh gọi Ajax tới bộ điều khiển để nhập dữ liệu trong các bộ nhỏ hơn. Bằng cách này, bạn sẽ không hết bộ nhớ vì nó sẽ khởi chạy một quy trình mới mỗi khi bạn thực hiện cuộc gọi Ajax đó thay vì liên tục phân bổ bộ nhớ vìMage::getModel('customer/address')


Đó là một cách giải quyết thú vị (+1 cho ý tưởng), nhưng tôi muốn một cái gì đó phù hợp hơn cho phần phụ trợ
pzirkind

1

Có vẻ như tôi đã tìm thấy một rò rỉ bộ nhớ lớn khi gọi Model::save()

Sau khi mục đã được lưu vào cơ sở dữ liệu, có đoạn mã sau trong phương thức được đề cập:

$this->_getResource()->addCommitCallback(array($this, 'afterCommitCallback'))

Bằng cách này, mô hình được thêm vào tham số tĩnh $_commitCallbacks. Phương thức sẽ bị xóa nếu mức giao dịch được đặt thành không.

Để giải quyết điều này, hãy thêm đoạn mã sau vào mô hình tài nguyên của riêng bạn:

public function addCommitCallback($callback)
{
    return $this;
    //return parent::addCommitCallback($callback);
}

Điều này chỉ hoạt động cho một loại mô hình tài nguyên, bạn cần thực hiện điều này với tất cả các mô hình tài nguyên được cập nhật thường xuyên trong vòng lặp của bạn. Một nhược điểm là phương pháp afterCommitCallback()mô hình của bạn không bao giờ được gọi.

Một khả năng khác (tốt hơn) là ghi đè lên commit()rollback()các phương thức và loại bỏ mô hình khỏi biến trong mọi trường hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.