現在、パフォーマンスに関していくつかのモジュールを改善しようとしています。
コレクションでのメソッドの使用法を知っている方もいるかもしれません。これは、製品を直接ループするのを回避するのに非常に役立ちます。walk()
さらに、@ Vinaiのおかげで、コレクションdelete()
メソッドを使用することもできます。
しかし、Magento 1のネイティブファイルは、これらの方法のいずれかを使用して削除するとは限らないことに気づきました。
私が見てきた最悪のコードの一つがあるmassDelete()
からメソッドapp/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
どこの製品は、削除前のループでロードされます。
foreach ($productIds as $productId) {
$product = Mage::getSingleton('catalog/product')->load($productId);
Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product));
$product->delete();
}
そこで、パフォーマンステストをいくつか行い、ロギングの呼び出しをいくつか追加して、100製品の削除にかかった時間とメモリ使用量を確認しました。
テスト1:walk
メソッド
上記に貼り付けた元のコードを次のコードに置き換えました。
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->walk('delete');
そして私の結果は私のくだらない開発サーバーで次のとおりです(10回のテストに基づく平均):
- 元のコード:19.97秒、15.84MB使用
- カスタムコード:17.12秒、15.45MB使用
したがって、100個の製品を削除すると、私のカスタムコードは3秒速くなり、使用するメモリは0.4MB少なくなります。
テスト2:コレクションdelete()
メソッドの使用
元のコードを次のコードに置き換えました:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('entity_id')
->addIdFilter($productIds)
->delete();
そしてここで吹き飛ばされた心は結果です:
- 元のコード:19.97秒、15.84MB使用
- カスタムコード:1.24秒、6.34MB使用
したがって、100個の製品を削除すると、私のカスタムコードは18秒速くなり、使用するメモリは9MB少なくなります。
コメントで述べたように、このメソッドはMagentoイベント(ロード後、削除後)も、インデックス/キャッシュフラッシュもトリガーしないようです。
質問
だから私の質問は:Magentoコアチームがループで製品をロードするのではなくwalk('delete')
、コレクションdelete()
メソッドを使用しない理由がありますか?
主な目標は、モジュール開発の場合は、そのようなキーポイントに注意することがある:1を使用することはできませんいずれかの特定の例があるwalk
/収集delete()
方法は?
編集:理由は間違いなくcatalog_controller_product_delete
同じコードがmassDelete
Magentoコアのいくつかの場所(メソッドをチェック)で見つけることができるので、イベントがディスパッチされているためではありません。製品の例を使用して、通常は最大のエンティティであるため、パフォーマンスを強調しました
delete()
コレクションをロードして各製品を削除する代わりに、DELETEクエリを作成します。それであなたは本当にイベントを失うでしょう。
getSingleton()
は、明らかなコレクションの使用法ではなく、特にパフォーマンス測定としての使用法は悪いスタイルです。walk()
ショートカットではなく、コレクションを使用してイベントをトリガーすることもできます。