That improvement https://github.com/mapbox/rasterio/pull/1444 has been lost while switching to WKT representation.
After:
In [1]: import rasterio
In [2]: rasterio.__version__
Out[2]: '1.0.14'
In [3]: from rasterio.crs import CRS
In [4]: c1 = CRS({'init': 'epsg:3857'})
In [5]: c2 = CRS({'init': 'epsg:3857'})
In [6]: %timeit c1 == c2
26.7 µs ± 370 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Before:
In [1]: import rasterio
In [2]: rasterio.__version__
Out[2]: '1.0.13'
In [3]: from rasterio.crs import CRS
In [4]: c1 = CRS({'init': 'epsg:3857'})
In [5]: c2 = CRS({'init': 'epsg:3857'})
In [6]: %timeit c1 == c2
204 ns ± 2.59 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
@drnextgis that particular use of the constructor is going to be deprecated in the future, so I haven't been considering performance. Can you try timing CRS.from_epsg(3857) ? If that is very slow, we should do something (such as memoize the EPSG code for rapid comparison).
I took the liberty to test the four combinations of rasterio 1.0.13 and 1.0.14 and pyproj 1.9.6 and 2.x. These are my results:
(_test36) juanlu@infinity ~ $ pip install "rasterio==1.0.13" "pyproj<2" > /dev/null 2>1
(_test36) juanlu@infinity ~ $ GDAL_DATA=$(rio env --gdal-data) ipython --no-banner
In [1]: import rasterio
...: print(rasterio.__version__)
...: import pyproj
...: print(pyproj.__version__)
...: from rasterio.crs import CRS
...:
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: c1 = CRS.from_epsg(3857)
...: c2 = CRS({'init': 'epsg:3857'})
...: %timeit c1 == c1
...: %timeit c1 == c2
...: %timeit c2 == c2
...:
1.0.13
1.9.6
83.7 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
13.4 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
17.2 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
14.8 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
262 ns ± 5.71 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
165 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
274 ns ± 18.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [2]:
Do you really want to exit ([y]/n)?
(_test36) juanlu@infinity ~ $ pip install "rasterio==1.0.13" "pyproj>=2" > /dev/null 2>1
(_test36) juanlu@infinity ~ $ GDAL_DATA=$(rio env --gdal-data) ipython --no-banner
In [1]: import rasterio
...: print(rasterio.__version__)
...: import pyproj
...: print(pyproj.__version__)
...: from rasterio.crs import CRS
...:
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: c1 = CRS.from_epsg(3857)
...: c2 = CRS({'init': 'epsg:3857'})
...: %timeit c1 == c1
...: %timeit c1 == c2
...: %timeit c2 == c2
...:
1.0.13
2.1.3
83.2 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
13.5 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
16.4 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
27.2 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
266 ns ± 8.88 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
157 µs ± 2.27 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
268 ns ± 15.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [2]:
Do you really want to exit ([y]/n)?
(_test36) juanlu@infinity ~ $ pip install "rasterio==1.0.14" "pyproj<2" > /dev/null 2>1
(_test36) juanlu@infinity ~ $ GDAL_DATA=$(rio env --gdal-data) ipython --no-banner
In [1]: import rasterio
...: print(rasterio.__version__)
...: import pyproj
...: print(pyproj.__version__)
...: from rasterio.crs import CRS
...:
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: c1 = CRS.from_epsg(3857)
...: c2 = CRS({'init': 'epsg:3857'})
...: %timeit c1 == c1
...: %timeit c1 == c2
...: %timeit c2 == c2
...:
1.0.14
1.9.6
1.32 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
102 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
78.1 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
74.5 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
96.5 µs ± 3.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
98.4 µs ± 5.87 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
95.6 µs ± 2.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [2]:
Do you really want to exit ([y]/n)?
(_test36) juanlu@infinity ~ $ pip install "rasterio==1.0.14" "pyproj>=2" > /dev/null 2>1
(_test36) juanlu@infinity ~ $ GDAL_DATA=$(rio env --gdal-data) ipython --no-banner
In [1]: import rasterio
...: print(rasterio.__version__)
...: import pyproj
...: print(pyproj.__version__)
...: from rasterio.crs import CRS
...:
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: c1 = CRS.from_epsg(3857)
...: c2 = CRS({'init': 'epsg:3857'})
...: %timeit c1 == c1
...: %timeit c1 == c2
...: %timeit c2 == c2
...:
1.0.14
2.1.3
1.33 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
97.1 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
118 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
141 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
98.8 µs ± 4.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
99.9 µs ± 3.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
98.2 µs ± 4.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
And this is the program I copy pasted:
import rasterio
print(rasterio.__version__)
import pyproj
print(pyproj.__version__)
from rasterio.crs import CRS
%timeit -n1 -r1 CRS({'init': 'epsg:3857'})
%timeit -n1 -r1 CRS({'init': 'epsg:3857'})
%timeit -n1 -r1 CRS.from_epsg(3857)
%timeit -n1 -r1 CRS.from_epsg(3857)
c1 = CRS.from_epsg(3857)
c2 = CRS({'init': 'epsg:3857'})
%timeit c1 == c1
%timeit c1 == c2
%timeit c2 == c2
I notice that:
CRS.from_epsg(3857)__eq__c1 == c1 initialized for both constructorsc1 == c2 when the initialization was different@Juanlu001 can you explain why you are reporting about pyproj in this issue? Rasterio doesn't use pyproj. Do you suspect some kind of conflict?
Is performance still a problem with Rasterio 1.1?
You're right about pyproj, I repeated my benchmarks:
In [2]: import rasterio
...: ...: print(rasterio.__version__)
...: ...: from rasterio.crs import CRS
...:
...: ...:
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: c1 = CRS.from_epsg(3857)
...: ...: c2 = CRS({'init': 'epsg:3857'})
...: ...: %timeit c1 == c1
...: ...: %timeit c1 == c2
...: ...: %timeit c2 == c2
1.0.13
22.3 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
11.3 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
14.7 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
14 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
594 ns ± 5.53 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
158 µs ± 7.11 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
590 ns ± 12.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [1]: import rasterio
...: ...: print(rasterio.__version__)
...: ...: from rasterio.crs import CRS
...:
...: ...:
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: c1 = CRS.from_epsg(3857)
...: ...: c2 = CRS({'init': 'epsg:3857'})
...: ...: %timeit c1 == c1
...: ...: %timeit c1 == c2
...: ...: %timeit c2 == c2
1.0.28
2.43 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
107 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
88.9 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
90.4 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
82.8 µs ± 757 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
86.2 µs ± 6.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
83.6 µs ± 1.24 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [1]: import rasterio
...: ...: print(rasterio.__version__)
...: ...: from rasterio.crs import CRS
...:
...: ...:
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS({'init': 'epsg:3857'})
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: %timeit -n1 -r1 CRS.from_epsg(3857)
...: ...: c1 = CRS.from_epsg(3857)
...: ...: c2 = CRS({'init': 'epsg:3857'})
...: ...: %timeit c1 == c1
...: ...: %timeit c1 == c2
...: ...: %timeit c2 == c2
1.1.2
2.35 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
108 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
89 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
87.9 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
83.3 µs ± 1.22 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
84.7 µs ± 2.56 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
83.1 µs ± 1.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
There is a very noticeable slowdown between 1.0.13 and 1.0.28 (which can be traced to 1.0.14 if I recall correctly) and no significant difference between 1.0.28 and 1.1.2.
Also, @sgillies could you please clarify which constructor will be deprecated?
that particular use of the constructor is going to be deprecated in the future, so I haven't been considering performance.
For future reference, according to some comments I've read in the pyproj documentation, I understand that the deprecated constructor is {"init": "epsg:3857"}.
In 604dca0 I have optimized the EPSG use case and observe sub-µsec equality comparison.
$ python -m timeit -s "from rasterio.crs import CRS" -s "epsg4326 = CRS.from_epsg(4326)" "epsg4326 == epsg4326"
1000000 loops, best of 3: 0.345 usec per loop
Most helpful comment
In 604dca0 I have optimized the EPSG use case and observe sub-µsec equality comparison.