Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_exportIterateCollection performance optimization #1467

Merged
merged 2 commits into from
Apr 6, 2021
Merged

_exportIterateCollection performance optimization #1467

merged 2 commits into from
Apr 6, 2021

Conversation

midlan
Copy link
Contributor

@midlan midlan commented Feb 18, 2021

Description (*)

In my opinion, there is no reason to export like:

  1. hey database, tell me the count of the data!
  2. if there is count > 0, give me the actual data

Instead of it, we can skip the step 1. and load the data immediately.

Related Pull Requests

Manual testing scenarios (*)

  1. use export feature of any grid widget pointing to getCsvFile method, e.g. tax rates grid

Contribution checklist (*)

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All automated tests passed successfully (all builds are green)

@github-actions github-actions bot added the Component: Adminhtml Relates to Mage_Adminhtml label Feb 18, 2021

foreach ($collection as $item) {
call_user_func_array(array($this, $callback), array_merge(array($item), $args));
}
$collection->clear();
unset($collection);
}

return $this;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this return to match the phpdoc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go the other way with it. Make the PhpDoc match what's actually happening.

There's no good reason why anyone should use this as a fluid interface. Too much return $this in Magento

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turned your note into code.


$count = $collection->count();

if ($count < $this->_exportPageSize) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't test this. But assuming $originalCollection has 1001 items, given that protected $_exportPageSize = 1000;, it will require 2 iterations. On the second iteration, $count will be 1, but it won't get exported since it'll break here. So, we need $break = true; instead of break;. Or am I missing something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am right, $count can be init to $this->_exportPageSize:

$originalCollection = $this->getCollection();
$count = $this->_exportPageSize;
//...
while ($count != $this->_exportPageSize) {
    //...
    $count = $collection->getSize(); // I prefer the standard method.
    // we can skip `if ($count < $this->_exportPageSize) {` and continue to export
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your thoughts seems right. My mistake. I swear I tested it, we are using the patched version in our Magento instance. I will test it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I figured it out. There is two methods getCsv and getCsvFile. Only getCsvFile is using _exportIterateCollection. But in most grids, the getCsv is used, so when I was testing my code, I actually run the other method. The right place to test it is tax rates grid:

https://yourwebsite/admin/tax_rate/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is fixed now and tested.

Copy link
Member

@colinmollenhour colinmollenhour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good improvement, count is very slow on some collections.

Copy link
Contributor

@kiatng kiatng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@kiatng kiatng added the performance Performance related label Feb 24, 2021
@Flyingmana Flyingmana merged commit f06d2bf into OpenMage:1.9.4.x Apr 6, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Apr 6, 2021

Unit Test Results

1 files  ±0  1 suites  ±0   0s ⏱️ ±0s
0 tests ±0  0 ✔️ ±0  0 💤 ±0  0 ❌ ±0 
2 runs  ±0  2 ✔️ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit f06d2bf. ± Comparison against base commit 39f9b0e.

drashmk pushed a commit to macopedia/magento-lts that referenced this pull request Dec 1, 2021
The infinite loop happens when you try to export collection that has number of items divisible by 1000(`$this->_exportPageSize`).
In this case the Varien collection will reset the page number to `lastPageNumber` when `$page` is higher.
`$page` is higher than `lastPageNumber` because the current logic assume that there is always one more page if the current page count is the same as page export size which is not true in case when count is divisible by page size.
@drashmk drashmk mentioned this pull request Dec 1, 2021
4 tasks
@tmotyl
Copy link
Contributor

tmotyl commented Dec 1, 2021

regression fix: #1888

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Adminhtml Relates to Mage_Adminhtml performance Performance related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants