@@ -172,10 +172,15 @@ def get_rates(self, rate, quote, bases, dts):
172172
173173 self ._check_dts (self .dts , dts )
174174
175- row_ixs = self .dts .searchsorted (dts , side = 'right' ) - 1
176- col_ixs = self .currencies .get_indexer (bases )
177-
178- return self ._read_rate_block (rate , quote , row_ixs , col_ixs )
175+ date_ixs = self .dts .searchsorted (dts , side = 'right' ) - 1
176+ currency_ixs = self .currencies .get_indexer (bases )
177+
178+ return self ._read_rate_block (
179+ rate ,
180+ quote ,
181+ row_ixs = date_ixs ,
182+ col_ixs = currency_ixs ,
183+ )
179184
180185 def _read_rate_block (self , rate , quote , row_ixs , col_ixs ):
181186 try :
@@ -186,10 +191,16 @@ def _read_rate_block(self, rate, quote, row_ixs, col_ixs):
186191 .format (rate , quote )
187192 )
188193
189- # There aren't many columns in the output array, so it's easier to pull
190- # all columns and reindex in memory. For rows, however, a quick and
191- # easy optimization is to pull just the slice from min(row_ixs) to
192- # max(row_ixs).
194+ # OPTIMIZATION: Row indices correspond to dates, which must be in
195+ # sorted order. Rather than reading the entire dataset from h5, we can
196+ # read just the interval from min_row to max_row inclusive.
197+ #
198+ # We don't bother with a similar optimization for columns because in
199+ # expectation we're going to load most of the
200+
201+ # array, so it's easier to pull all columns and reindex in memory. For
202+ # rows, however, a quick and easy optimization is to pull just the
203+ # slice from min(row_ixs) to max(row_ixs).
193204 min_row = row_ixs [0 ]
194205 max_row = row_ixs [- 1 ]
195206 rows = dataset [min_row :max_row + 1 ] # +1 to be inclusive of end
0 commit comments