Repository: modin-project/modin
Pull request: PERF-#5550: Don't trigger axes computation in `to_pandas` function
Signed-off-by: Anatoly Myachev <anatoly.myachev@intel.com>

<!--
Thank you for your contribution!
Please review the contributing docs: https://modin.readthedocs.io/en/latest/development/contributing.html
if you have questions about contributing.
-->

## What do these changes do?

<!-- Please give a short brief about these changes. -->

- [x] first commit message and PR title follow format outlined [here](https://modin.readthedocs.io/en/latest/development/contributing.html#commit-message-formatting)
  > **_NOTE:_**  If you edit the PR title to match this format, you need to add another commit (even if it's empty) or amend your last commit for the CI job that checks the PR title to pick up the new PR title.
- [x] passes `flake8 modin/ asv_bench/benchmarks scripts/doc_checker.py`
- [x] passes `black --check modin/ asv_bench/benchmarks scripts/doc_checker.py`
- [x] signed commit with `git commit -s` <!-- you can amend your commit with a signature via `git commit -amend -s` -->
- [x] Resolves #5550 <!-- issue must be created for each patch -->
- [x] tests added and passing
- [x] module layout described at `docs/development/architecture.rst` is up-to-date <!-- if you have added, renamed or removed files or directories please update the documentation accordingly -->


Problem statement:
don't trigger axes computation in `to_pandas` function 
In the case when the indexes are not materialized, we get them from internal partitions. However, then they are compared with the indexes of the dataframe obtained from the internal partitions. In this case, we know in advance that they will be the same. 
Looks like extra work that can be avoided.

Hints from issue discussion:

Commit message: PERF-#0000: don't trigger axes computation in 'to_pandas' function

Signed-off-by: Anatoly Myachev <anatoly.myachev@intel.com>

Patch to review:
diff --git a/modin/core/dataframe/pandas/dataframe/dataframe.py b/modin/core/dataframe/pandas/dataframe/dataframe.py
index 795888ab021..35f04664f94 100644
--- a/modin/core/dataframe/pandas/dataframe/dataframe.py
+++ b/modin/core/dataframe/pandas/dataframe/dataframe.py
@@ -3230,13 +3230,16 @@ def to_pandas(self):
         if df.empty:
             df = pandas.DataFrame(columns=self.columns, index=self.index)
         else:
-            for axis in [0, 1]:
-                ErrorMessage.catch_bugs_and_request_email(
-                    not df.axes[axis].equals(self.axes[axis]),
-                    f"Internal and external indices on axis {axis} do not match.",
-                )
-            df.index = self.index
-            df.columns = self.columns
+            if self._index_cache is not None and self._columns_cache is not None:
+                # no need to check external and internal axes since in that case
+                # external axes will be computed from internal partitions
+                for axis in [0, 1]:
+                    ErrorMessage.catch_bugs_and_request_email(
+                        not df.axes[axis].equals(self.axes[axis]),
+                        f"Internal and external indices on axis {axis} do not match.",
+                    )
+                df.index = self.index
+                df.columns = self.columns
 
         return df
 


Code review comments:
diff_hunk: @@ -3230,13 +3230,16 @@ def to_pandas(self):
         if df.empty:
             df = pandas.DataFrame(columns=self.columns, index=self.index)
         else:
-            for axis in [0, 1]:
-                ErrorMessage.catch_bugs_and_request_email(
-                    not df.axes[axis].equals(self.axes[axis]),
-                    f"Internal and external indices on axis {axis} do not match.",
-                )
-            df.index = self.index
-            df.columns = self.columns
+            if self._index_cache is not None and self._columns_cache is not None:
+                # no need to check external and internal axes since in that case
+                # external axes will be computed from internal partitions
+                for axis in [0, 1]:
+                    ErrorMessage.catch_bugs_and_request_email(
+                        not df.axes[axis].equals(self.axes[axis]),
+                        f"Internal and external indices on axis {axis} do not match.",
+                    )
+                df.index = self.index
+                df.columns = self.columns
path: modin/core/dataframe/pandas/dataframe/dataframe.py
text: @user1:
We may want to preserve the logic at least partially:
```suggestion
            for axis, public_index in enumerate([self._index_cache, self._columns_cache]):
                # no need to check external and internal axes since in that case
                # external axes will be computed from internal partitions
                if public_index is not None:
                    ErrorMessage.catch_bugs_and_request_email(
                        not df.axes[axis].equals(public_index),
                        f"Internal and external indices on axis {axis} do not match.",
                    )
                    df.set_axis(axis=axis, labels=public_index, inplace=True, copy=False)
```

@author:
good catch!