## Python using NaN or None as sentinel

Comparing to `None`

instead of `NaN`

is:

- 4..50 times faster in CPython
- more than 1000 times faster in PyPy3 with Numpy, same speed with
`math`

Benchamrks using Intel Coffee Lake CPU with:

```
ipython
```

Python 3.7.3 IPython 7.7.0 Numpy 1.16.4

```
pypy3 -m IPython
```

Python 3.6.1 (PyPy3 7.1.1)

**Numpy** is well known to be slower at scalar operations than pure Python.
But many data science and STEM application using arrays are vastly faster and more convenient with Numpy than pure Python methods.

```
from numpy import isnan
%timeit isnan(0.)
```

- CPython: 428 ns ± 1.74 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

### Python NaN

```
from math import isnan
%timeit isnan(0.)
```

- CPython: 45.7 ns ± 0.209 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
- PyPy3: 0.988 ns ± 0.00506 ns per loop (mean ± std. dev. of 7 runs, 1000000000 loops each)

### Python None

```
%timeit 0. is not None
```

- CPython: 17 ns ± 0.328 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
- PyPy3: 0.987 ns ± 0.0041 ns per loop (mean ± std. dev. of 7 runs, 1000000000 loops each)

### Numba

using python-performance

```
python NoneVsNan.py
```

```
--> Numba NaN sentinel: 1.00e-07
--> Numba None sentinel: 1.00e-07
--> CPython NaN sentinel: 2.00e-07
--> Numpy NaN sentinel: 6.00e-07
--> CPython None sentinel: 1.00e-07
```