Windows CI
xref https://github.com/pandas-dev/pandas/issues/23180

Trying to ensure we get the pyarrow from main, not conda-forge.
https://dev.azure.com/pandas-dev/pandas/_build/results?buildId=1261&view=logs

I cancelled the other builds. Welp, the arrow failure seems to be fixed (thanks @h-vetinari)

But now I think our old friend https://github.com/pandas-dev/pandas/issues/21786 is back perhaps?

```
2018-10-16T14:46:56.4427066Z ================================== FAILURES ===================================
2018-10-16T14:46:56.4429803Z __________ TestApi.test_multiple_agg_funcs[rolling-2-expected_vals0] __________
2018-10-16T14:46:56.4430094Z [gw1] win32 -- Python 3.6.6 C:\Miniconda\envs\pandas\python.exe
2018-10-16T14:46:56.4430210Z 
2018-10-16T14:46:56.4430674Z self = <pandas.tests.test_window.TestApi object at 0x000001BEBBE95CC0>
2018-10-16T14:46:56.4431798Z func = 'rolling', window_size = 2
2018-10-16T14:46:56.4432414Z expected_vals = [[nan, nan, nan, nan], [15.0, 20.0, 25.0, 20.0], [25.0, 30.0, 35.0, 30.0], [nan, nan, nan, nan], [20.0, 30.0, 35.0, 30.0], [35.0, 40.0, 60.0, 40.0], ...]
2018-10-16T14:46:56.4433525Z 
2018-10-16T14:46:56.4433684Z     @pytest.mark.parametrize("func,window_size,expected_vals", [
2018-10-16T14:46:56.4433870Z         ('rolling', 2, [[np.nan, np.nan, np.nan, np.nan],
2018-10-16T14:46:56.4434208Z                         [15., 20., 25., 20.],
2018-10-16T14:46:56.4434613Z                         [25., 30., 35., 30.],
2018-10-16T14:46:56.4435474Z                         [np.nan, np.nan, np.nan, np.nan],
2018-10-16T14:46:56.4435544Z                         [20., 30., 35., 30.],
2018-10-16T14:46:56.4435854Z                         [35., 40., 60., 40.],
2018-10-16T14:46:56.4436266Z                         [60., 80., 85., 80]]),
2018-10-16T14:46:56.4436779Z         ('expanding', None, [[10., 10., 20., 20.],
2018-10-16T14:46:56.4437141Z                              [15., 20., 25., 20.],
2018-10-16T14:46:56.4437986Z                              [20., 30., 30., 20.],
2018-10-16T14:46:56.4438067Z                              [10., 10., 30., 30.],
2018-10-16T14:46:56.4438397Z                              [20., 30., 35., 30.],
2018-10-16T14:46:56.4438860Z                              [26.666667, 40., 50., 30.],
2018-10-16T14:46:56.4439321Z                              [40., 80., 60., 30.]])])
2018-10-16T14:46:56.4440299Z     def test_multiple_agg_funcs(self, func, window_size, expected_vals):
2018-10-16T14:46:56.4440597Z         # GH 15072
2018-10-16T14:46:56.4440731Z         df = pd.DataFrame([
2018-10-16T14:46:56.4440875Z             ['A', 10, 20],
2018-10-16T14:46:56.4444532Z             ['A', 20, 30],
2018-10-16T14:46:56.4445692Z             ['A', 30, 40],
2018-10-16T14:46:56.4445965Z             ['B', 10, 30],
2018-10-16T14:46:56.4446254Z             ['B', 30, 40],
2018-10-16T14:46:56.4446547Z             ['B', 40, 80],
2018-10-16T14:46:56.4447045Z             ['B', 80, 90]], columns=['stock', 'low', 'high'])
2018-10-16T14:46:56.4447255Z     
2018-10-16T14:46:56.4447656Z         f = getattr(df.groupby('stock'), func)
2018-10-16T14:46:56.4447932Z         if window_size:
2018-10-16T14:46:56.4448319Z             window = f(window_size)
2018-10-16T14:46:56.4448585Z         else:
2018-10-16T14:46:56.4449275Z             window = f()
2018-10-16T14:46:56.4449401Z     
2018-10-16T14:46:56.4449654Z         index = pd.MultiIndex.from_tuples([
2018-10-16T14:46:56.4449945Z             ('A', 0), ('A', 1), ('A', 2),
2018-10-16T14:46:56.4450512Z             ('B', 3), ('B', 4), ('B', 5), ('B', 6)], names=['stock', None])
2018-10-16T14:46:56.4450921Z         columns = pd.MultiIndex.from_tuples([
2018-10-16T14:46:56.4451754Z             ('low', 'mean'), ('low', 'max'), ('high', 'mean'),
2018-10-16T14:46:56.4451854Z             ('high', 'min')])
2018-10-16T14:46:56.4452236Z         expected = pd.DataFrame(expected_vals, index=index, columns=columns)
2018-10-16T14:46:56.4452829Z     
2018-10-16T14:46:56.4453277Z         result = window.agg(OrderedDict((
2018-10-16T14:46:56.4453663Z             ('low', ['mean', 'max']),
2018-10-16T14:46:56.4454003Z             ('high', ['mean', 'min']),
2018-10-16T14:46:56.4454617Z         )))
2018-10-16T14:46:56.4454928Z     
2018-10-16T14:46:56.4455007Z >       tm.assert_frame_equal(result, expected)
2018-10-16T14:46:56.4455046Z 
2018-10-16T14:46:56.4455480Z pandas\tests\test_window.py:362: 
2018-10-16T14:46:56.4456659Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2018-10-16T14:46:56.4457099Z pandas\util\testing.py:1457: in assert_frame_equal
2018-10-16T14:46:56.4457539Z     obj='DataFrame.iloc[:, {idx}]'.format(idx=i))
2018-10-16T14:46:56.4458491Z pandas\util\testing.py:1292: in assert_series_equal
2018-10-16T14:46:56.4458636Z     obj='{obj}'.format(obj=obj))
2018-10-16T14:46:56.4459084Z pandas\_libs\testing.pyx:66: in pandas._libs.testing.assert_almost_equal
2018-10-16T14:46:56.4459458Z     cpdef assert_almost_equal(a, b,
2018-10-16T14:46:56.4460905Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2018-10-16T14:46:56.4461361Z 
2018-10-16T14:46:56.4461523Z >   raise_assert_detail(obj, msg, lobj, robj)
2018-10-16T14:46:56.4461755Z E   AssertionError: DataFrame.iloc[:, 0] are different
2018-10-16T14:46:56.4461882Z E   
2018-10-16T14:46:56.4462057Z E   DataFrame.iloc[:, 0] values are different (71.42857 %)
2018-10-16T14:46:56.4462334Z E   [left]:  [nan, nan, nan, nan, nan, nan, nan]
2018-10-16T14:46:56.4463072Z E   [right]: [nan, 15.0, 25.0, nan, 20.0, 35.0, 60.0]
2018-10-16T14:46:56.4463235Z 
```

cc @chris-b1. # [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23182?src=pr&el=h1) Report
> Merging [#23182](https://codecov.io/gh/pandas-dev/pandas/pull/23182?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/e8d29e73e68630620908eaf28589f0882c294e53?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/23182/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/23182?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master   #23182   +/-   ##
=======================================
  Coverage   92.19%   92.19%           
=======================================
  Files         169      169           
  Lines       50956    50956           
=======================================
  Hits        46977    46977           
  Misses       3979     3979
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.61% <ø> (ø)` | :arrow_up: |
| #single | `42.27% <ø> (ø)` | :arrow_up: |


------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23182?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/23182?src=pr&el=footer). Last update [e8d29e7...6af3461](https://codecov.io/gh/pandas-dev/pandas/pull/23182?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
 I think https://dev.azure.com/pandas-dev/pandas/_settings/agentqueues?queueId=3&_a=details may have the details of that worker, if that means anything to anyone. So the `pyarrow` import still wasn't fully sorted, because later on in the log, `import pyarrow.parquet` failed (also for me locally). Adding `parquet-cpp` to the list of requirements should get it from `main` (I ran `conda install parquet-cpp` and got an alternative to `conda-forge`), and then the import works again for me.

Regarding the `window` failures (which I *can't* reproduce), there's a follow-up to @chris-b1's MVSC bug report [here](https://developercommunity.visualstudio.com/comments/345660/view.html), which recommends - until MVSC is fixed upstream - to bracket `_libs.window.{add_var|add_mean|remove_mean}` with `#pragma optimize("", off)` [...] `#pragma optimize("", on)`. Do pragmas get included in the code generated by Cython? Based on some limited testing / searching, I don't think they do...

Regardless, I thought https://github.com/pandas-dev/pandas/pull/21813 that, so maybe it's a different issue. c512f42 is a bit of a hammer. I don't intend to actually merge it. Remaining failures should be solved with:
> So the `pyarrow` import still wasn't fully sorted, because later on in the log, `import pyarrow.parquet` failed (also for me locally). Adding `parquet-cpp` to the list of requirements should get it from `main` (I ran `conda install parquet-cpp` and got an alternative to `conda-forge`), and then the import works again for me.

https://github.com/pandas-dev/pandas/commit/c512f4200be5147e9e8a11a46a45d2cb0a406031 did work, but then that points to the same underlying error as in #21786, no? > c512f42 did work, but then that points to the same underlying error as in #21786, no?

Seems like it. @chris-b1 is there a reason you applied the `isnan` fix only in those places? Is using it everywhere like I did a bad idea?
 There's likely a little performance cost, because the call to isnan won't
be inlined, but otherwise might need to be applied everywhere.

On Tue, Oct 16, 2018, 3:04 PM Tom Augspurger <notifications@github.com>
wrote:

> c512f42
> <https://github.com/pandas-dev/pandas/commit/c512f4200be5147e9e8a11a46a45d2cb0a406031>
> did work, but then that points to the same underlying error as in #21786
> <https://github.com/pandas-dev/pandas/issues/21786>, no?
>
> Seems like it. @chris-b1 <https://github.com/chris-b1> is there a reason
> you applied the isnan fix only in those places? Is using it everywhere
> like I did a bad idea?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/pandas-dev/pandas/pull/23182#issuecomment-430380363>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AB1b_GBXGpt4pkQYlWisi0xSguOCcSD2ks5uljvJgaJpZM4XeZIq>
> .
>
 So, this (possible) perf hit would be on all platforms correct, not just windows with MSVC_VER < 1800?

(How) do we know that the compiler doesn't inline it? I assume you discovered that when debugging originally...

I'll try to be a bit more surgical in where we apply it Locally, with these changes

```
       before           after         ratio
     [7ef69bdb]       [c512f420]
     <fix-windows-ci~2>       <fix-windows-ci~1>
+     2.13±0.04ms       2.85±0.3ms     1.34  rolling.Quantile.time_quantile('DataFrame', 1000, 'float', 0, 'lower')
+     1.48±0.01ms       1.92±0.1ms     1.30  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 1, 'lower')
+      18.6±0.3ms         24.1±1ms     1.30  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'int', 'std')
+        73.6±1ms         93.8±3ms     1.27  rolling.Quantile.time_quantile('Series', 1000, 'float', 0.5, 'lower')
+     1.86±0.03ms       2.33±0.3ms     1.25  rolling.Quantile.time_quantile('Series', 1000, 'int', 1, 'midpoint')
+     1.58±0.09ms      1.97±0.07ms     1.25  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 1, 'higher')
+     1.67±0.01ms      2.04±0.05ms     1.23  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 1, 'nearest')
+      72.5±0.7ms         88.5±3ms     1.22  rolling.Quantile.time_quantile('Series', 1000, 'float', 0.5, 'nearest')
+        72.1±1ms         87.5±2ms     1.21  rolling.Quantile.time_quantile('Series', 1000, 'float', 0.5, 'higher')
+     2.14±0.07ms       2.60±0.1ms     1.21  rolling.Quantile.time_quantile('DataFrame', 1000, 'float', 0, 'higher')
+     1.78±0.07ms       2.16±0.2ms     1.21  rolling.Quantile.time_quantile('Series', 1000, 'int', 1, 'linear')
+     2.34±0.03ms      2.81±0.09ms     1.20  rolling.Quantile.time_quantile('Series', 1000, 'float', 0, 'higher')
+     4.60±0.03ms         5.45±1ms     1.19  rolling.VariableWindowMethods.time_rolling('Series', '1h', 'float', 'skew')
+     3.16±0.04ms       3.73±0.5ms     1.18  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'int', 'count')
+     1.62±0.03ms       1.91±0.1ms     1.18  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0, 'linear')
+     2.84±0.02ms      3.32±0.08ms     1.17  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'float', 'sum')
+     1.87±0.03ms       2.18±0.2ms     1.17  rolling.Quantile.time_quantile('Series', 1000, 'int', 1, 'higher')
+     2.34±0.04ms       2.72±0.1ms     1.16  rolling.Quantile.time_quantile('Series', 1000, 'float', 0, 'lower')
+      56.6±0.8ms         65.7±2ms     1.16  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0.5, 'lower')
+     1.92±0.03ms       2.22±0.3ms     1.16  rolling.Quantile.time_quantile('Series', 1000, 'int', 0, 'linear')
+        57.6±2ms         66.7±3ms     1.16  rolling.Quantile.time_quantile('Series', 1000, 'int', 0.5, 'lower')
+     1.96±0.02ms      2.26±0.09ms     1.15  rolling.Quantile.time_quantile('DataFrame', 10, 'float', 1, 'linear')
+     2.41±0.02ms       2.78±0.1ms     1.15  rolling.Quantile.time_quantile('Series', 1000, 'float', 0, 'nearest')
+         116±2ms          133±1ms     1.15  rolling.VariableWindowMethods.time_rolling('DataFrame', '1d', 'float', 'median')
+      63.8±0.7ms         73.1±6ms     1.15  rolling.Quantile.time_quantile('Series', 1000, 'int', 0.5, 'linear')
+     2.23±0.03ms       2.56±0.3ms     1.15  rolling.Quantile.time_quantile('Series', 10, 'float', 1, 'midpoint')
+      64.5±0.9ms         73.8±2ms     1.14  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0.5, 'midpoint')
+      50.8±0.4ms       58.0±0.7ms     1.14  rolling.Quantile.time_quantile('Series', 10, 'float', 0.5, 'lower')
+     1.81±0.03ms      2.06±0.08ms     1.14  rolling.Quantile.time_quantile('Series', 10, 'int', 0, 'nearest')
+      56.6±0.8ms         64.3±1ms     1.14  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0.5, 'nearest')
+     1.63±0.02ms      1.85±0.04ms     1.14  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0, 'midpoint')
+        77.3±1ms        87.8±10ms     1.14  rolling.Quantile.time_quantile('Series', 1000, 'float', 0.5, 'linear')
+     2.22±0.02ms      2.52±0.06ms     1.13  rolling.Quantile.time_quantile('Series', 10, 'float', 0, 'nearest')
+      65.0±0.5ms         73.7±4ms     1.13  rolling.Quantile.time_quantile('Series', 1000, 'int', 0.5, 'midpoint')
+     1.91±0.01ms      2.16±0.02ms     1.13  rolling.Quantile.time_quantile('DataFrame', 10, 'float', 0, 'nearest')
+      52.5±0.6ms         59.3±3ms     1.13  rolling.Quantile.time_quantile('Series', 10, 'float', 0.5, 'midpoint')
+      63.4±0.4ms         71.5±4ms     1.13  rolling.Quantile.time_quantile('DataFrame', 1000, 'int', 0.5, 'linear')
+     2.83±0.04ms       3.18±0.2ms     1.12  rolling.VariableWindowMethods.time_rolling('DataFrame', '1h', 'int', 'sum')
+     1.91±0.04ms      2.14±0.05ms     1.12  rolling.Quantile.time_quantile('Series', 1000, 'int', 1, 'nearest')
+      74.9±0.6ms         84.1±3ms     1.12  rolling.VariableWindowMethods.time_rolling('DataFrame', '1h', 'float', 'median')
+     4.43±0.02ms      4.96±0.09ms     1.12  rolling.VariableWindowMethods.time_rolling('DataFrame', '1d', 'float', 'skew')
+     1.53±0.06ms      1.71±0.03ms     1.12  rolling.Quantile.time_quantile('DataFrame', 10, 'int', 1, 'lower')
+     2.41±0.04ms      2.70±0.05ms     1.12  rolling.Quantile.time_quantile('Series', 1000, 'float', 0, 'linear')
+     2.23±0.03ms       2.50±0.2ms     1.12  rolling.Quantile.time_quantile('Series', 10, 'float', 1, 'nearest')
+     2.93±0.06ms       3.28±0.1ms     1.12  rolling.VariableWindowMethods.time_rolling('DataFrame', '1d', 'float', 'count')
+     2.42±0.03ms       2.71±0.1ms     1.12  rolling.Quantile.time_quantile('Series', 1000, 'float', 1, 'linear')
+     3.28±0.06ms      3.67±0.07ms     1.12  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'int', 'count')
+     2.99±0.03ms      3.35±0.05ms     1.12  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'float', 'mean')
+     2.23±0.02ms       2.49±0.2ms     1.12  rolling.Quantile.time_quantile('Series', 10, 'float', 1, 'lower')
+     2.43±0.05ms       2.71±0.1ms     1.12  rolling.Quantile.time_quantile('Series', 1000, 'float', 1, 'lower')
+     2.01±0.05ms      2.25±0.03ms     1.12  rolling.Quantile.time_quantile('DataFrame', 10, 'float', 1, 'lower')
+     4.63±0.06ms      5.17±0.07ms     1.12  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'int', 'max')
+     1.80±0.01ms      2.00±0.07ms     1.11  rolling.Quantile.time_quantile('Series', 10, 'int', 0, 'midpoint')
+     1.80±0.01ms      2.00±0.07ms     1.11  rolling.Quantile.time_quantile('Series', 10, 'int', 0, 'higher')
+     2.20±0.01ms       2.45±0.2ms     1.11  rolling.Quantile.time_quantile('Series', 10, 'float', 1, 'higher')
+     1.54±0.05ms      1.71±0.03ms     1.11  rolling.Quantile.time_quantile('DataFrame', 10, 'int', 1, 'higher')
+     2.96±0.06ms      3.29±0.05ms     1.11  rolling.VariableWindowMethods.time_rolling('Series', '1h', 'int', 'sum')
+     2.90±0.07ms      3.22±0.05ms     1.11  rolling.VariableWindowMethods.time_rolling('DataFrame', '50s', 'int', 'mean')
+     1.82±0.03ms      2.02±0.08ms     1.11  rolling.Quantile.time_quantile('Series', 10, 'int', 1, 'lower')
+     2.42±0.03ms      2.68±0.04ms     1.11  rolling.Quantile.time_quantile('Series', 1000, 'float', 1, 'higher')
+         107±1ms          119±3ms     1.11  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'int', 'median')
+      4.33±0.1ms       4.78±0.1ms     1.11  rolling.VariableWindowMethods.time_rolling('DataFrame', '1d', 'int', 'max')
+     4.37±0.07ms       4.82±0.1ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'int', 'min')
+     3.10±0.03ms      3.42±0.02ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'float', 'count')
+     3.04±0.01ms      3.35±0.06ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'float', 'mean')
+     4.58±0.04ms      5.05±0.08ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '1h', 'float', 'min')
+     2.82±0.03ms      3.11±0.04ms     1.10  rolling.VariableWindowMethods.time_rolling('DataFrame', '1d', 'float', 'mean')
+     3.08±0.04ms      3.40±0.06ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'int', 'mean')
+     2.22±0.06ms      2.45±0.08ms     1.10  rolling.Quantile.time_quantile('Series', 10, 'float', 0, 'lower')
+     3.07±0.02ms      3.38±0.05ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '1h', 'int', 'mean')
+         120±2ms          133±2ms     1.10  rolling.VariableWindowMethods.time_rolling('Series', '1d', 'float', 'median')
+     6.75±0.08ms       7.43±0.2ms     1.10  rolling.VariableWindowMethods.time_rolling('DataFrame', '1h', 'int', 'kurt')
+     1.99±0.03ms      2.20±0.01ms     1.10  rolling.Quantile.time_quantile('DataFrame', 10, 'float', 0, 'lower')
+     2.38±0.02ms      2.62±0.01ms     1.10  rolling.Quantile.time_quantile('Series', 1000, 'float', 1, 'nearest')

```

so that's not a great solution...

Is there a way to define a function (or macro?) that winds up as

```python
if x == x
```

on non-windows machines, and as the more complicated `if not isnan(x)` when we detect MSVC 2017 is being used? @TomAugspurger : Can't you leverage the pragma's used in [cmath.h](https://github.com/pandas-dev/pandas/blob/b5313f923c829388d043f9c7b7bc2adf62c2dd89/pandas/_libs/src/headers/cmath#L6)? I'm not sure. And I'm not sure how to convince the compiler that it should be inlined. Trying out 29f392c, but I don't know C / C++ so thoughts from others would be appreciated.

I'm running ASV over the rolling benchmarks now. A couple questions:

I see some new warnings in the build logs

```
2018-10-17T11:02:00.9761682Z     pandas\_libs/window.cpp(9522) : warning C4244: 'argument' : conversion from '__pyx_t_5numpy_int64_t' to 'int', possible loss of data
2018-10-17T11:02:00.9761814Z     pandas\_libs/window.cpp(16928) : warning C4244: '=' : conversion from 'double' to '__pyx_t_5numpy_float32_t', possible loss of data
```

I suppose it's fine, but should I explicitly cast the int to float first?

 ASV with this version looks a bit better maybe. Re-running those slow ones, to see if it's just noise.

```
       before           after         ratio
     [b5313f92]       [29f392c4]
     <fix-windows-ci~1>       <fix-windows-ci>
+     3.01±0.04ms         4.69±2ms     1.56  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'int', 'sum')
+     4.69±0.03ms         6.47±2ms     1.38  rolling.VariableWindowMethods.time_rolling('Series', '50s', 'float', 'max')
+      18.8±0.2ms       21.8±0.8ms     1.16  rolling.VariableWindowMethods.time_rolling('DataFrame', '1h', 'int', 'std')

``` No changes on `asv continuous c512f4200..HEAD -b rolling.VariableWindowMethods.time_rolling`, so I think things are being inlined now hopefully (at least on linux / Mac). I think the MSVC versions this is being applied to is incorrect.

The CI failure is on Version: VisualStudio/15.8.5+28010.2036. According to https://stackoverflow.com/a/70630/1889400, that's `_MSVC_VER == 1915`. I guess I had a slight different fix in mind than @chris-b1.  I'd like to replace all uses of `if val == val` with `if notnan(val)`.

On the versions affected by the bug, (MSVC 1910 through 1915?), we would need that to be `not isnan(val)`.

On the versions not affected by the bug (other platforms, older MSVC, and in a future patched MSVC), that would be just `{return x == x;}` 

So I'm thinking

```cpp
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && (_MSC_VER < 2000)
#include <cmath>
namespace std {
  __inline int isnan(double x) { return _isnan(x); }
  __inline int signbit(double num) { return _copysign(1.0, num) < 0; }
  __inline int notnan(double x) { return not isnan(x); }
}
#else
#include <cmath>

namespace std {
  __inline int notnan(double x) { return x == x; }
}

#endif
#endif
```

I'm not sure we even need the `isnan` and `isgnbit` anymore, since IIUC, MSVC 2017 has those defined already? 0b7dc84 attempts that.

Reminder that I don't know what I'm doing here, and I don't have a windows machine, so this should get a close look from the experts :) Latest tries to work around

```
2018-10-17T13:14:47.3917605Z     d:\a\1\s\pandas\_libs\src/headers/cmath(11): error C2883: 'std::signbit': function declaration conflicts with 'signbit' introduced by using-declaration
2018-10-17T13:14:47.3917664Z     C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt\corecrt_math.h(310): note: see declaration of 'signbit'
``` The azure 36 build passed. @chris-b1 do you have time today to take a look at the changes? Thanks for grinding through this, I'll have time to look later this
afternoon

On Wed, Oct 17, 2018, 8:57 AM Tom Augspurger <notifications@github.com>
wrote:

> The azure 36 build passed. @chris-b1 <https://github.com/chris-b1> do you
> have time today to take a look at the changes?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/pandas-dev/pandas/pull/23182#issuecomment-430638394>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AB1b_HtfUL7ujKuDrK8RFmc8y8qZ-Pugks5ulzcwgaJpZM4XeZIq>
> .
>
 Merging in a couple hours if no objections (cc @jreback if you haven't had a look yet) this was fine