PERF: faster unstacking
State: closed

closes #15503

so on a non-masked unstack (IOW, a fully product multi-index for example), this is now just
a simple reshape. On a masked unstack, it now will have a much lower O constant, as its in cython, and with release the GIL.

0.19.2 / master
```
In [2]: m = 100
   ...: n = 1000
   ...: 
   ...: levels = np.arange(m)
   ...: index = pd.MultiIndex.from_product([levels]*2)
   ...: columns = np.arange(n)
   ...: values = np.arange(m*m*n).reshape(m*m, n)
   ...: df = pd.DataFrame(values, index, columns)
   ...: 

In [3]: %timeit df.unstack()
1 loop, best of 3: 285 ms per loop

In [4]: df2 = df.iloc[:-1]

In [5]: %timeit df2.unstack()
1 loop, best of 3: 306 ms per loop
```

PR
```
In [2]: %timeit df.unstack()
10 loops, best of 3: 70 ms per loop

In [3]: df2 = df.iloc[:-1]

# & releasing the GIL here.
In [4]: %timeit df2.unstack()
1 loop, best of 3: 191 ms per loop
```


Labels:
name: Performance
description: Memory or execution speed performance
name: Reshaping
description: Concat, Merge/Join, Stack/Unstack, Explode

Comments:
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15510?src=pr&el=h1) Report
> Merging [#15510](https://codecov.io/gh/pandas-dev/pandas/pull/15510?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/cd677043dcfc4c6b48a6b1ad89da395a35d10e49?src=pr&el=desc) will **decrease** coverage by `-0.03%`.
> The diff coverage is `100%`.


```diff
@@            Coverage Diff             @@
##           master   #15510      +/-   ##
==========================================
- Coverage   91.04%   91.02%   -0.03%     
==========================================
  Files         136      136              
  Lines       49088    49105      +17     
==========================================
+ Hits        44694    44698       +4     
- Misses       4394     4407      +13
```


| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/15510?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/reshape.py](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvcmVzaGFwZS5weQ==) | `99.27% <100%> (+0.02%)` | :white_check_mark: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :x: |
| [pandas/tools/merge.py](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=tree#diff-cGFuZGFzL3Rvb2xzL21lcmdlLnB5) | `91.78% <0%> (-0.35%)` | :x: |
| [pandas/util/testing.py](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvdGVzdGluZy5weQ==) | `81.87% <0%> (-0.19%)` | :x: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.82% <0%> (-0.1%)` | :x: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15510?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15510?src=pr&el=footer). Last update [cd67704...ec29226](https://codecov.io/gh/pandas-dev/pandas/compare/cd677043dcfc4c6b48a6b1ad89da395a35d10e49...ec292260cf11f3c938969d342a47f170b50a9117?src=pr&el=footer&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
cc @wesm if you have a chance.