Skip to content

DEP: Use Cython 3.0 #55179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 16, 2023
Merged

Conversation

rhshadrach
Copy link
Member

@rhshadrach rhshadrach commented Sep 17, 2023

  • closes #xxxx (Replace xxxx with the GitHub issue number)
  • Tests added and passed if fixing a bug or adding a new feature
  • All code checks passed.
  • Added type annotations to new arguments/methods/functions.
  • Added an entry in the latest doc/source/whatsnew/vX.X.X.rst file if fixing a bug or adding a new feature.

We're seeing some perf regressions (but also a lot of perf improvements) by using Cython 3.0. Not sure what the best way to approach this is - do we try to handle fixing these in a single branch along with changing to 3.0? Or do we just adopt 3.0 in one PR and try to address the regressions after?

ASV Regressions for Cython 3.0
| Change   | Before [e89d18c8] <main>   | After [71693857] <unpin_cython_everywhere>   |   Ratio | Benchmark (Parameter)                                                                                                                                                   |
|----------|----------------------------|----------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| +        | 1.14±0ms                   | 2.64±0.1ms                                   |    2.32 | series_methods.Fillna.time_ffill('Int64')                                                                                                                               |
| +        | 1.16±0.01ms                | 2.66±0.1ms                                   |    2.3  | series_methods.Fillna.time_ffill('Float64')                                                                                                                             |
| +        | 1.24±0.3ms                 | 2.69±0.4ms                                   |    2.17 | series_methods.Fillna.time_ffill('datetime64[ns]')                                                                                                                      |
| +        | 1.14±0.01ms                | 1.84±0.04ms                                  |    1.61 | series_methods.Fillna.time_bfill('Float64')                                                                                                                             |
| +        | 1.13±0.01ms                | 1.78±0.05ms                                  |    1.57 | series_methods.Fillna.time_bfill('Int64')                                                                                                                               |
| +        | 6.87±0.2ms                 | 9.88±0.06ms                                  |    1.44 | algos.isin.IsinWithRandomFloat.time_isin(<class 'numpy.object_'>, 80000, 'outside')                                                                                     |
| +        | 111±7μs                    | 157±4μs                                      |    1.42 | algos.isin.IsInForObjects.time_isin('short', 'nans')                                                                                                                    |
| +        | 3.12±0.2ms                 | 4.12±0.03ms                                  |    1.32 | algos.isin.IsInForObjects.time_isin('long_floats', 'long_floats')                                                                                                       |
| +        | 49.5±2ms                   | 61.8±2ms                                     |    1.25 | index_object.IntervalIndexMethod.time_intersection_both_duplicate(100000)                                                                                               |
| +        | 797±8ms                    | 999±20ms                                     |    1.25 | strings.Dummies.time_get_dummies('str')                                                                                                                                 |
| +        | 13.3±0.2ms                 | 16.4±0.04ms                                  |    1.23 | indexing.MultiIndexing.time_loc_all_lists(True)                                                                                                                         |
| +        | 892±7ms                    | 1.10±0.01s                                   |    1.23 | strings.Dummies.time_get_dummies('string[pyarrow]')                                                                                                                     |
| +        | 8.71±0.06ms                | 10.5±0.4ms                                   |    1.21 | index_object.SetOperations.time_operation('non_monotonic', 'date_string', 'symmetric_difference')                                                                       |
| +        | 10.7±0.3ms                 | 12.6±0.1ms                                   |    1.18 | algorithms.Duplicated.time_duplicated(False, False, 'float64')                                                                                                          |
| +        | 250±2μs                    | 294±5μs                                      |    1.18 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.float64'>, 3.0, <built-in function lt>)                                                           |
| +        | 23.2±0.07ms                | 27.1±0.09ms                                  |    1.17 | groupby.GroupByCythonAggEaDtypes.time_frame_agg('Int32', 'last')                                                                                                        |
| +        | 421±20ns                   | 491±20ns                                     |    1.17 | index_cached_properties.IndexCache.time_shape('Int64Index')                                                                                                             |
| +        | 955±10ms                   | 1.12±0.02s                                   |    1.17 | strings.Dummies.time_get_dummies('string[python]')                                                                                                                      |
| +        | 187±6μs                    | 218±10μs                                     |    1.16 | algos.isin.IsInForObjects.time_isin('nans', 'nans')                                                                                                                     |
| +        | 29.6±0.1ms                 | 34.5±0.4ms                                   |    1.16 | groupby.GroupByCythonAggEaDtypes.time_frame_agg('Float64', 'mean')                                                                                                      |
| +        | 32.0±0.3ms                 | 37.2±0.5ms                                   |    1.16 | groupby.GroupByCythonAggEaDtypes.time_frame_agg('Int32', 'mean')                                                                                                        |
| +        | 347±10ns                   | 402±7ns                                      |    1.16 | tslibs.timestamp.TimestampOps.time_to_pydatetime(datetime.timezone(datetime.timedelta(seconds=3600)))                                                                   |
| +        | 348±8ns                    | 404±8ns                                      |    1.16 | tslibs.timestamp.TimestampOps.time_to_pydatetime(datetime.timezone.utc)                                                                                                 |
| +        | 117±0.5ns                  | 135±8ns                                      |    1.16 | tslibs.timestamp.TimestampProperties.time_quarter(None)                                                                                                                 |
| +        | 11.0±0.6ms                 | 12.6±0.5ms                                   |    1.15 | algorithms.Duplicated.time_duplicated(False, False, 'datetime64[ns, tz]')                                                                                               |
| +        | 11.0±0.4ms                 | 12.6±0.4ms                                   |    1.15 | algorithms.Duplicated.time_duplicated(False, False, 'datetime64[ns]')                                                                                                   |
| +        | 256±6μs                    | 294±7μs                                      |    1.15 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.float64'>, 3.0, <built-in function gt>)                                                           |
| +        | 11.8±0.2ms                 | 13.6±0.1ms                                   |    1.15 | indexing.DataFrameNumericIndexing.time_loc_dups(<class 'numpy.float64'>, 'nonunique_monotonic_inc')                                                                     |
| +        | 202±20μs                   | 230±3μs                                      |    1.14 | algos.isin.IsIn.time_isin('str')                                                                                                                                        |
| +        | 208±20μs                   | 237±3μs                                      |    1.14 | algos.isin.IsIn.time_isin_categorical('str')                                                                                                                            |
| +        | 345±9ns                    | 394±6ns                                      |    1.14 | tslibs.timestamp.TimestampOps.time_to_pydatetime(None)                                                                                                                  |
| +        | 352±9ns                    | 402±10ns                                     |    1.14 | tslibs.timestamp.TimestampOps.time_to_pydatetime(tzfile('/usr/share/zoneinfo/Asia/Tokyo'))                                                                              |
| +        | 353±10ns                   | 404±10ns                                     |    1.14 | tslibs.timestamp.TimestampOps.time_to_pydatetime(tzlocal())                                                                                                             |
| +        | 5.20±0.3ms                 | 5.86±0.1ms                                   |    1.13 | algorithms.Duplicated.time_duplicated(False, 'last', 'datetime64[ns]')                                                                                                  |
| +        | 207±20μs                   | 234±0.9μs                                    |    1.13 | algos.isin.IsIn.time_isin('string[python]')                                                                                                                             |
| +        | 496±40μs                   | 558±6μs                                      |    1.13 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.float64'>, 2, <built-in function add>)                                                            |
| +        | 76.1±1μs                   | 86.1±3μs                                     |    1.13 | indexing.MultiIndexing.time_xs_full_key(True)                                                                                                                           |
| +        | 349±10ns                   | 394±6ns                                      |    1.13 | tslibs.timestamp.TimestampOps.time_to_pydatetime(<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                                      |
| +        | 118±2ns                    | 133±10ns                                     |    1.13 | tslibs.timestamp.TimestampProperties.time_is_year_start(<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                               |
| +        | 213±20μs                   | 239±2μs                                      |    1.12 | algos.isin.IsIn.time_isin_categorical('string[python]')                                                                                                                 |
| +        | 4.95±0.1ms                 | 5.56±0.06ms                                  |    1.12 | tslibs.normalize.Normalize.time_normalize_i8_timestamps(1000000, datetime.timezone(datetime.timedelta(seconds=3600)))                                                   |
| +        | 280±20ns                   | 311±30ns                                     |    1.11 | index_cached_properties.IndexCache.time_is_unique('Int64Index')                                                                                                         |
| +        | 104±1ns                    | 116±3ns                                      |    1.11 | tslibs.timestamp.TimestampProperties.time_is_year_end(None)                                                                                                             |
| +        | 7.48±0.05ms                | 8.25±0.2ms                                   |    1.1  | frame_methods.Dropna.time_dropna_axis_mixed_dtypes('any', 0)                                                                                                            |
| +        | 1.89±0.01ms                | 2.09±0.04ms                                  |    1.1  | frame_methods.Fillna.time_bfill(False, 'Int64')                                                                                                                         |
| +        | 21.3±0.2ms                 | 23.5±0.3ms                                   |    1.1  | groupby.GroupByCythonAgg.time_frame_agg('float64', 'mean')                                                                                                              |
| +        | 51.6±0.4ms                 | 56.9±0.2ms                                   |    1.1  | io.csv.ToCSV.time_frame('long')                                                                                                                                         |
| +        | 1.68±0.02ms                | 1.85±0.1ms                                   |    1.1  | join_merge.Concat.time_concat_series(0)                                                                                                                                 |
| +        | 52.8±0.6μs                 | 58.3±0.5μs                                   |    1.1  | tslibs.normalize.Normalize.time_normalize_i8_timestamps(10000, datetime.timezone(datetime.timedelta(seconds=3600)))                                                     |
| +        | 115±1ns                    | 127±7ns                                      |    1.1  | tslibs.timestamp.TimestampProperties.time_days_in_month(None)                                                                                                           |
| +        | 121±0.6ns                  | 133±8ns                                      |    1.1  | tslibs.timestamp.TimestampProperties.time_quarter(datetime.timezone.utc)

I'm hoping the gil.* regressions will be fixed by cython/cython#5685 GIL regressions are now gone.

@rhshadrach
Copy link
Member Author

rhshadrach commented Sep 17, 2023

I couldn't post the ASVs at once as it was too large for a GitHub comment.

ASV Perf increases
| -        | 28.0±0.2μs                                      | 25.4±0.3μs                                   |    0.91 | algos.isin.IsinAlmostFullWithRandomInt.time_isin(<class 'numpy.int64'>, 10, 'outside')                                                                                  |
| -        | 37.6±0.1μs                                      | 34.2±0.3μs                                   |    0.91 | groupby.GroupByMethods.time_dtype_as_group('int16', 'cummax', 'direct', 1, 'cython')                                                                                    |
| -        | 312±6ns                                         | 282±9ns                                      |    0.91 | index_object.Float64IndexMethod.time_get_loc                                                                                                                            |
| -        | 2.76±0.01μs                                     | 2.51±0.09μs                                  |    0.91 | indexing.NumericSeriesIndexing.time_iloc_scalar(<class 'numpy.uint64'>, 'unique_monotonic_inc')                                                                         |
| -        | 95.9±3ms                                        | 86.8±0.3ms                                   |    0.91 | inference.ToNumericDowncast.time_downcast('string-nint', 'integer')                                                                                                     |
| -        | 82.7±0.3ns                                      | 74.9±0.4ns                                   |    0.91 | libs.ScalarListLike.time_is_list_like([1, 2, 3])                                                                                                                        |
| -        | 92.7±1ns                                        | 84.2±0.8ns                                   |    0.91 | libs.ScalarListLike.time_is_scalar((1, 2, 3))                                                                                                                           |
| -        | 84.2±1ns                                        | 76.3±0.9ns                                   |    0.91 | libs.ScalarListLike.time_is_scalar(b'bar')                                                                                                                              |
| -        | 81.5±0.1ns                                      | 73.9±0.1ns                                   |    0.91 | libs.ScalarListLike.time_is_scalar(numpy.timedelta64(123,'ns'))                                                                                                         |
| -        | 58.5±0.2μs                                      | 53.0±0.2μs                                   |    0.91 | period.Indexing.time_intersection                                                                                                                                       |
| -        | 1.97±0.01ms                                     | 1.79±0.01ms                                  |    0.91 | rolling.VariableWindowMethods.time_method('Series', '1h', 'float', 'skew')                                                                                              |
| -        | 14.9±0.1ms                                      | 13.6±0.2ms                                   |    0.91 | strings.Methods.time_fullmatch('string[python]')                                                                                                                        |
| -        | 18.0±0.08ms                                     | 16.4±0.04ms                                  |    0.91 | strings.Methods.time_pad('str')                                                                                                                                         |
| -        | 671±20μs                                        | 608±1μs                                      |    0.91 | strings.StringArrayConstruction.time_string_array_construction                                                                                                          |
| -        | 1.80±0.06ms                                     | 1.63±0ms                                     |    0.91 | timeseries.DatetimeIndex.time_timeseries_is_month_start('tz_aware')                                                                                                     |
| -        | 1.03±0.01μs                                     | 933±1ns                                      |    0.91 | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(0, 'start', 'month', 'QS', 3)                                                                               |
| -        | 4.17±0.1μs                                      | 3.78±0.03μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<QuarterBegin: startingMonth=3>)                                                                                       |
| -        | 4.16±0.08μs                                     | 3.78±0.02μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<YearEnd: month=12>)                                                                                                   |
| -        | 4.86±0.1μs                                      | 4.40±0.06μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<QuarterEnd: startingMonth=3>)                                                                                      |
| -        | 4.68±0.1μs                                      | 4.24±0.04μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<SemiMonthBegin: day_of_month=15>)                                                                                  |
| -        | 4.72±0.06μs                                     | 4.29±0.09μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<YearBegin: month=1>)                                                                                               |
| -        | 4.80±0.2μs                                      | 4.36±0.05μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<BYearEnd: month=12>)                                                                                             |
| -        | 6.35±0.2μs                                      | 5.76±0.01μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<BusinessDay>)                                                                                                 |
| -        | 5.16±0.09μs                                     | 4.69±0.02μs                                  |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<SemiMonthBegin: day_of_month=15>)                                                                             |
| -        | 5.17±0.08μs                                     | 4.69±0.1μs                                   |    0.91 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<SemiMonthEnd: day_of_month=15>)                                                                               |
| -        | 358±5ns                                         | 324±6ns                                      |    0.91 | tslibs.period.TimePeriodArrToDT64Arr.time_periodarray_to_dt64arr(0, 12000)                                                                                              |
| -        | 120±2μs                                         | 108±1μs                                      |    0.9  | algos.isin.IsinWithRandomFloat.time_isin(<class 'numpy.object_'>, 1300, 'outside')                                                                                      |
| -        | 621±20μs                                        | 556±40μs                                     |    0.9  | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.int64'>, 4, <built-in function mul>)                                                              |
| -        | 1.57±0.02ms                                     | 1.42±0.01ms                                  |    0.9  | frame_methods.Fillna.time_ffill(True, 'Float64')                                                                                                                        |
| -        | 2.49±0.05ms                                     | 2.23±0.06ms                                  |    0.9  | gil.ParallelRolling.time_rolling('skew')                                                                                                                                |
| -        | 37.3±0.1μs                                      | 33.5±0.7μs                                   |    0.9  | groupby.GroupByMethods.time_dtype_as_field('int', 'cummax', 'direct', 1, 'cython')                                                                                      |
| -        | 38.2±0.2μs                                      | 34.6±0.4μs                                   |    0.9  | groupby.GroupByMethods.time_dtype_as_group('uint', 'cummax', 'direct', 1, 'cython')                                                                                     |
| -        | 2.27±0.01μs                                     | 2.04±0.03μs                                  |    0.9  | indexing.CategoricalIndexIndexing.time_getitem_slice('monotonic_decr')                                                                                                  |
| -        | 2.27±0.01μs                                     | 2.04±0.03μs                                  |    0.9  | indexing.CategoricalIndexIndexing.time_getitem_slice('monotonic_incr')                                                                                                  |
| -        | 2.28±0.01μs                                     | 2.06±0.01μs                                  |    0.9  | indexing.CategoricalIndexIndexing.time_getitem_slice('non_monotonic')                                                                                                   |
| -        | 5.12±0.02μs                                     | 4.60±0.02μs                                  |    0.9  | indexing.MultiIndexing.time_loc_partial_key_null_slice(False)                                                                                                           |
| -        | 5.10±0.04μs                                     | 4.61±0.03μs                                  |    0.9  | indexing.MultiIndexing.time_loc_partial_key_null_slice(True)                                                                                                            |
| -        | 2.78±0.01μs                                     | 2.51±0.06μs                                  |    0.9  | indexing.NumericSeriesIndexing.time_iloc_scalar(<class 'numpy.int64'>, 'unique_monotonic_inc')                                                                          |
| -        | 2.76±0.02μs                                     | 2.50±0.05μs                                  |    0.9  | indexing.NumericSeriesIndexing.time_iloc_scalar(<class 'numpy.uint64'>, 'nonunique_monotonic_inc')                                                                      |
| -        | 95.9±3ms                                        | 86.3±0.5ms                                   |    0.9  | inference.ToNumericDowncast.time_downcast('string-nint', 'float')                                                                                                       |
| -        | 96.6±3ms                                        | 86.5±0.2ms                                   |    0.9  | inference.ToNumericDowncast.time_downcast('string-nint', 'signed')                                                                                                      |
| -        | 95.9±3ms                                        | 86.2±0.3ms                                   |    0.9  | inference.ToNumericDowncast.time_downcast('string-nint', 'unsigned')                                                                                                    |
| -        | 453±1ns                                         | 409±0.8ns                                    |    0.9  | libs.InferDtype.time_infer_dtype('empty')                                                                                                                               |
| -        | 81.4±0.5ns                                      | 73.3±0.3ns                                   |    0.9  | libs.ScalarListLike.time_is_list_like(array([1, 2, 3]))                                                                                                                 |
| -        | 118±0.3ns                                       | 106±0.9ns                                    |    0.9  | libs.ScalarListLike.time_is_list_like(b'bar')                                                                                                                           |
| -        | 83.9±0.6ns                                      | 75.7±0.3ns                                   |    0.9  | libs.ScalarListLike.time_is_scalar(0)                                                                                                                                   |
| -        | 90.8±0.2ns                                      | 82.0±1ns                                     |    0.9  | libs.ScalarListLike.time_is_scalar(None)                                                                                                                                |
| -        | 84.1±0.2ns                                      | 75.7±0.6ns                                   |    0.9  | libs.ScalarListLike.time_is_scalar(True)                                                                                                                                |
| -        | 81.4±0.2ns                                      | 72.9±0.2ns                                   |    0.9  | libs.ScalarListLike.time_is_scalar(numpy.datetime64('1970-01-01T00:00:00.000000123'))                                                                                   |
| -        | 5.58±0.06ms                                     | 5.03±0.1ms                                   |    0.9  | reindex.DropDuplicates.time_frame_drop_dups(False)                                                                                                                      |
| -        | 1.57±0.01s                                      | 1.41±0s                                      |    0.9  | replace.ReplaceDict.time_replace_series(True)                                                                                                                           |
| -        | 1.97±0ms                                        | 1.76±0.04ms                                  |    0.9  | rolling.Methods.time_method('DataFrame', ('rolling', {'window': 1000}), 'int', 'skew')                                                                                  |
| -        | 1.96±0ms                                        | 1.76±0.02ms                                  |    0.9  | rolling.Methods.time_method('DataFrame', ('rolling', {'window': 10}), 'float', 'skew')                                                                                  |
| -        | 1.97±0.01ms                                     | 1.77±0.05ms                                  |    0.9  | rolling.Methods.time_method('DataFrame', ('rolling', {'window': 10}), 'int', 'skew')                                                                                    |
| -        | 1.89±0.01ms                                     | 1.69±0.02ms                                  |    0.9  | rolling.Methods.time_method('Series', ('rolling', {'window': 1000}), 'int', 'skew')                                                                                     |
| -        | 1.88±0.01ms                                     | 1.68±0.03ms                                  |    0.9  | rolling.Methods.time_method('Series', ('rolling', {'window': 10}), 'float', 'skew')                                                                                     |
| -        | 1.90±0.01ms                                     | 1.70±0.02ms                                  |    0.9  | rolling.Methods.time_method('Series', ('rolling', {'window': 10}), 'int', 'skew')                                                                                       |
| -        | 2.08±0.01ms                                     | 1.88±0.02ms                                  |    0.9  | rolling.VariableWindowMethods.time_method('DataFrame', '1h', 'int', 'skew')                                                                                             |
| -        | 2.07±0ms                                        | 1.87±0.02ms                                  |    0.9  | rolling.VariableWindowMethods.time_method('DataFrame', '50s', 'float', 'skew')                                                                                          |
| -        | 1.98±0ms                                        | 1.78±0.03ms                                  |    0.9  | rolling.VariableWindowMethods.time_method('Series', '50s', 'float', 'skew')                                                                                             |
| -        | 1.99±0ms                                        | 1.80±0.02ms                                  |    0.9  | rolling.VariableWindowMethods.time_method('Series', '50s', 'int', 'skew')                                                                                               |
| -        | 17.5±0.08ms                                     | 15.7±0.6ms                                   |    0.9  | strings.Methods.time_fullmatch('str')                                                                                                                                   |
| -        | 15.9±0.3ms                                      | 14.3±0.3ms                                   |    0.9  | strings.Methods.time_get('string[pyarrow]')                                                                                                                             |
| -        | 14.3±0.1ms                                      | 12.8±0.2ms                                   |    0.9  | strings.Methods.time_get('string[python]')                                                                                                                              |
| -        | 22.2±0.06ms                                     | 20.1±0.1ms                                   |    0.9  | strings.Methods.time_rfind('str')                                                                                                                                       |
| -        | 16.1±0.6ms                                      | 14.6±0.5ms                                   |    0.9  | strings.Methods.time_title('string[pyarrow]')                                                                                                                           |
| -        | 1.92±0.05ms                                     | 1.74±0ms                                     |    0.9  | timeseries.DatetimeAccessor.time_dt_accessor_year('US/Eastern')                                                                                                         |
| -        | 1.08±0.03μs                                     | 966±7ns                                      |    0.9  | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(0, 'end', 'quarter', 'QS', 3)                                                                               |
| -        | 1.04±0.01μs                                     | 939±2ns                                      |    0.9  | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(0, 'start', 'month', 'QS', 12)                                                                              |
| -        | 1.11±0.04μs                                     | 994±3ns                                      |    0.9  | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(1, 'end', 'quarter', 'QS', 5)                                                                               |
| -        | 1.08±0μs                                        | 970±1ns                                      |    0.9  | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(1, 'start', 'year', 'QS', 3)                                                                                |
| -        | 287±10ns                                        | 257±0.8ns                                    |    0.9  | tslibs.normalize.Normalize.time_is_date_array_normalized(0, datetime.timezone.utc)                                                                                      |
| -        | 287±10ns                                        | 257±0.7ns                                    |    0.9  | tslibs.normalize.Normalize.time_is_date_array_normalized(1, datetime.timezone.utc)                                                                                      |
| -        | 4.19±0.09μs                                     | 3.79±0.05μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_add(<BYearEnd: month=12>)                                                                                                  |
| -        | 4.26±0.1μs                                      | 3.83±0.06μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_add(<BusinessQuarterBegin: startingMonth=3>)                                                                               |
| -        | 4.16±0.1μs                                      | 3.76±0.06μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_add(<YearBegin: month=1>)                                                                                                  |
| -        | 4.50±0.09μs                                     | 4.05±0.01μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<MonthBegin>)                                                                                                       |
| -        | 4.82±0.2μs                                      | 4.35±0.06μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<QuarterBegin: startingMonth=3>)                                                                                    |
| -        | 4.47±0.1μs                                      | 4.03±0.06μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<BusinessMonthBegin>)                                                                                             |
| -        | 4.51±0.06μs                                     | 4.04±0.01μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<BusinessMonthEnd>)                                                                                               |
| -        | 4.84±0.1μs                                      | 4.36±0.05μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<QuarterEnd: startingMonth=3>)                                                                                    |
| -        | 4.80±0.08μs                                     | 4.30±0.02μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<BusinessMonthEnd>)                                                                                            |
| -        | 5.31±0.2μs                                      | 4.76±0.05μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<BusinessQuarterBegin: startingMonth=3>)                                                                       |
| -        | 4.75±0.1μs                                      | 4.28±0.02μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<MonthEnd>)                                                                                                    |
| -        | 5.32±0.1μs                                      | 4.78±0.07μs                                  |    0.9  | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<QuarterBegin: startingMonth=3>)                                                                               |
| -        | 4.09±0.2μs                                      | 3.67±0.02μs                                  |    0.9  | tslibs.period.PeriodUnaryMethods.time_asfreq('M')                                                                                                                       |
| -        | 1.62±0.02μs                                     | 1.46±0.01μs                                  |    0.9  | tslibs.period.TimePeriodArrToDT64Arr.time_periodarray_to_dt64arr(1, 7000)                                                                                               |
| -        | 605±20ns                                        | 545±0.8ns                                    |    0.9  | tslibs.timestamp.TimestampConstruction.time_from_datetime_aware                                                                                                         |
| -        | 587±6ns                                         | 530±1ns                                      |    0.9  | tslibs.timestamp.TimestampConstruction.time_from_datetime_unaware                                                                                                       |
| -        | 122±0.3ns                                       | 109±2ns                                      |    0.9  | tslibs.timestamp.TimestampOps.time_tz_convert(None)                                                                                                                     |
| -        | 125±1ns                                         | 112±1ns                                      |    0.9  | tslibs.timestamp.TimestampOps.time_tz_localize(<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                                        |
| -        | 122±0.3ns                                       | 110±6ns                                      |    0.9  | tslibs.timestamp.TimestampProperties.time_tz(datetime.timezone(datetime.timedelta(seconds=3600)))                                                                       |
| -        | 353±30ns                                        | 314±4ns                                      |    0.89 | attrs_caching.SeriesArrayAttribute.time_extract_array('object')                                                                                                         |
| -        | 357±30ns                                        | 319±1ns                                      |    0.89 | attrs_caching.SeriesArrayAttribute.time_extract_array_numpy('datetime64')                                                                                               |
| -        | 357±30ns                                        | 316±1ns                                      |    0.89 | attrs_caching.SeriesArrayAttribute.time_extract_array_numpy('datetime64tz')                                                                                             |
| -        | 80.1±2ms                                        | 71.3±5ms                                     |    0.89 | gil.ParallelReadCSV.time_read_csv('float')                                                                                                                              |
| -        | 26.2±0.3ms                                      | 23.3±0.1ms                                   |    0.89 | groupby.GroupByCythonAggEaDtypes.time_frame_agg('Int32', 'first')                                                                                                       |
| -        | 38.5±0.8μs                                      | 34.4±0.7μs                                   |    0.89 | groupby.GroupByMethods.time_dtype_as_field('float', 'last', 'direct', 1, 'cython')                                                                                      |
| -        | 1.15±0.05μs                                     | 1.02±0.05μs                                  |    0.89 | index_cached_properties.IndexCache.time_inferred_type('Float64Index')                                                                                                   |
| -        | 81.7±0.3ns                                      | 72.6±0.3ns                                   |    0.89 | libs.ScalarListLike.time_is_scalar(1.0)                                                                                                                                 |
| -        | 91.4±0.1ns                                      | 81.7±0.04ns                                  |    0.89 | libs.ScalarListLike.time_is_scalar(<NA>)                                                                                                                                |
| -        | 1.95±0.01ms                                     | 1.73±0.05ms                                  |    0.89 | rolling.Methods.time_method('DataFrame', ('rolling', {'window': 1000}), 'float', 'skew')                                                                                |
| -        | 1.88±0ms                                        | 1.68±0.02ms                                  |    0.89 | rolling.Methods.time_method('Series', ('rolling', {'window': 1000}), 'float', 'skew')                                                                                   |
| -        | 2.06±0.01ms                                     | 1.84±0.05ms                                  |    0.89 | rolling.VariableWindowMethods.time_method('DataFrame', '1h', 'float', 'skew')                                                                                           |
| -        | 15.7±0.2ms                                      | 14.1±0.6ms                                   |    0.89 | strings.Methods.time_match('str')                                                                                                                                       |
| -        | 12.6±0.3ms                                      | 11.2±0.3ms                                   |    0.89 | strings.Methods.time_normalize('string[pyarrow]')                                                                                                                       |
| -        | 14.9±0.06ms                                     | 13.3±0.05ms                                  |    0.89 | strings.Methods.time_title('str')                                                                                                                                       |
| -        | 15.1±0.06ms                                     | 13.4±0.03ms                                  |    0.89 | strings.Methods.time_title('string[python]')                                                                                                                            |
| -        | 7.45±0.2μs                                      | 6.64±0.03μs                                  |    0.89 | timeseries.AsOf.time_asof_single('Series')                                                                                                                              |
| -        | 1.05±0.03μs                                     | 940±2ns                                      |    0.89 | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(0, 'end', 'month', 'QS', 3)                                                                                 |
| -        | 1.07±0.02μs                                     | 948±2ns                                      |    0.89 | tslibs.fields.TimeGetStartEndField.time_get_start_end_field(0, 'end', 'year', 'QS', 12)                                                                                 |
| -        | 343±9ns                                         | 305±0.7ns                                    |    0.89 | tslibs.normalize.Normalize.time_is_date_array_normalized(0, None)                                                                                                       |
| -        | 341±9ns                                         | 304±0.7ns                                    |    0.89 | tslibs.normalize.Normalize.time_is_date_array_normalized(1, None)                                                                                                       |
| -        | 4.15±0.08μs                                     | 3.68±0.02μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<BusinessMonthBegin>)                                                                                                  |
| -        | 4.11±0.1μs                                      | 3.65±0.02μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<MonthEnd>)                                                                                                            |
| -        | 4.26±0.1μs                                      | 3.81±0.03μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<QuarterEnd: startingMonth=3>)                                                                                         |
| -        | 4.55±0.09μs                                     | 4.06±0.02μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<BusinessMonthEnd>)                                                                                                 |
| -        | 4.82±0.07μs                                     | 4.31±0.06μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<BusinessQuarterBegin: startingMonth=3>)                                                                            |
| -        | 4.52±0.1μs                                      | 4.03±0.04μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<MonthEnd>)                                                                                                         |
| -        | 6.40±0.2μs                                      | 5.70±0.08μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BusinessDay>)                                                                                                 |
| -        | 4.83±0.08μs                                     | 4.29±0.06μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<BusinessQuarterBegin: startingMonth=3>)                                                                          |
| -        | 4.47±0.2μs                                      | 4.00±0.09μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<MonthEnd>)                                                                                                       |
| -        | 4.83±0.09μs                                     | 4.30±0.08μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<QuarterBegin: startingMonth=3>)                                                                                  |
| -        | 4.69±0.07μs                                     | 4.16±0.03μs                                  |    0.89 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<SemiMonthEnd: day_of_month=15>)                                                                                  |
| -        | 4.17±0.02μs                                     | 3.72±0.04μs                                  |    0.89 | tslibs.period.PeriodUnaryMethods.time_asfreq('min')                                                                                                                     |
| -        | 813±40ns                                        | 724±3ns                                      |    0.89 | tslibs.timestamp.TimestampOps.time_tz_convert(datetime.timezone.utc)                                                                                                    |
| -        | 123±3ns                                         | 110±2ns                                      |    0.89 | tslibs.timestamp.TimestampOps.time_tz_localize(datetime.timezone.utc)                                                                                                   |
| -        | 122±3ns                                         | 108±0.4ns                                    |    0.89 | tslibs.timestamp.TimestampProperties.time_tz(<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                                          |
| -        | 9.25±0.6ms                                      | 8.20±0.01ms                                  |    0.89 | tslibs.tz_convert.TimeTZConvert.time_tz_convert_from_utc(1000000, <DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                     |
| -        | 2.27±0.03ms                                     | 2.01±0.01ms                                  |    0.88 | frame_ctor.FromArrays.time_frame_from_arrays_sparse                                                                                                                     |
| -        | 1.87±0.03ms                                     | 1.65±0.02ms                                  |    0.88 | frame_methods.Fillna.time_bfill(False, 'Float64')                                                                                                                       |
| -        | 2.29±0.05ms                                     | 2.03±0.02ms                                  |    0.88 | frame_methods.Fillna.time_bfill(False, 'datetime64[ns, tz]')                                                                                                            |
| -        | 4.89±0.1ms                                      | 4.28±0.05ms                                  |    0.88 | frame_methods.Isna.time_isna('Float64')                                                                                                                                 |
| -        | 36.7±0.2μs                                      | 32.1±0.2μs                                   |    0.88 | groupby.GroupByMethods.time_dtype_as_field('int', 'cummin', 'direct', 1, 'cython')                                                                                      |
| -        | 218±3ns                                         | 193±1ns                                      |    0.88 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_decr', True, 100000)                    |
| -        | 5.97±0.05ms                                     | 5.29±0.06ms                                  |    0.88 | timeseries.Iteration.time_iter_preexit(<function period_range>)                                                                                                         |
| -        | 4.16±0.1μs                                      | 3.67±0.04μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<BusinessMonthEnd>)                                                                                                    |
| -        | 4.12±0.07μs                                     | 3.64±0.03μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<MonthBegin>)                                                                                                          |
| -        | 4.15±0.1μs                                      | 3.67±0.02μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<SemiMonthBegin: day_of_month=15>)                                                                                     |
| -        | 4.16±0.1μs                                      | 3.67±0.03μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<SemiMonthEnd: day_of_month=15>)                                                                                       |
| -        | 4.76±0.1μs                                      | 4.19±0.02μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<SemiMonthEnd: day_of_month=15>)                                                                                    |
| -        | 4.47±0.08μs                                     | 3.94±0.07μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<MonthBegin>)                                                                                                     |
| -        | 4.85±0.1μs                                      | 4.28±0.08μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<BusinessMonthBegin>)                                                                                          |
| -        | 4.82±0.06μs                                     | 4.25±0.01μs                                  |    0.88 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<MonthBegin>)                                                                                                  |
| -        | 113±0.5ns                                       | 100±1ns                                      |    0.88 | tslibs.timestamp.TimestampConstruction.time_from_pd_timestamp                                                                                                           |
| -        | 122±0.7ns                                       | 107±1ns                                      |    0.88 | tslibs.timestamp.TimestampProperties.time_tz(tzlocal())                                                                                                                 |
| -        | 8.81±0.1μs                                      | 7.71±0.03μs                                  |    0.87 | boolean.TimeLogicalOps.time_xor_scalar                                                                                                                                  |
| -        | 218±5ns                                         | 191±0.9ns                                    |    0.87 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'non_monotonic', True, 100000)                     |
| -        | 226±4ns                                         | 196±2ns                                      |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_decr', True, 100000)              |
| -        | 232±5ns                                         | 203±0.9ns                                    |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_decr', True, 2000000)             |
| -        | 222±6ns                                         | 192±0.2ns                                    |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_decr', True, 2000000)                 |
| -        | 216±3ns                                         | 188±1ns                                      |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'non_monotonic', True, 100000)                   |
| -        | 221±4ns                                         | 192±2ns                                      |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'non_monotonic', True, 2000000)                  |
| -        | 234±6ns                                         | 203±2ns                                      |    0.87 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_decr', True, 2000000) |
| -        | 37.1±0.7ms                                      | 32.4±0.8ms                                   |    0.87 | io.parsers.DoesStringLookLikeDatetime.time_check_datetimes('10000')                                                                                                     |
| -        | 12.1±0.06ms                                     | 10.5±0.01ms                                  |    0.87 | strings.Methods.time_endswith('str')                                                                                                                                    |
| -        | 551±6ms                                         | 477±7ms                                      |    0.87 | timeseries.Iteration.time_iter(<function period_range>)                                                                                                                 |
| -        | 4.26±0.1μs                                      | 3.73±0.08μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BYearBegin: month=1>)                                                                                         |
| -        | 4.29±0.2μs                                      | 3.72±0.08μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BYearEnd: month=12>)                                                                                          |
| -        | 4.36±0.1μs                                      | 3.80±0.04μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BusinessQuarterEnd: startingMonth=3>)                                                                         |
| -        | 4.24±0.1μs                                      | 3.68±0.09μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<YearBegin: month=1>)                                                                                          |
| -        | 4.27±0.1μs                                      | 3.71±0.08μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<YearEnd: month=12>)                                                                                           |
| -        | 4.78±0.1μs                                      | 4.18±0.03μs                                  |    0.87 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<SemiMonthBegin: day_of_month=15>)                                                                                |
| -        | 596±3ns                                         | 516±5ns                                      |    0.87 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(0, <DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                            |
| -        | 514±4ns                                         | 448±4ns                                      |    0.87 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(1, datetime.timezone.utc)                                                                                       |
| -        | 6.22±0.2ms                                      | 5.33±0.2ms                                   |    0.86 | algorithms.Duplicated.time_duplicated(False, 'first', 'datetime64[ns]')                                                                                                 |
| -        | 693±7μs                                         | 599±10μs                                     |    0.86 | algos.isin.IsInForObjects.time_isin('long', 'nans')                                                                                                                     |
| -        | 324±2μs                                         | 278±4μs                                      |    0.86 | frame_methods.AsType.time_astype(('Float64', 'Float64'), True)                                                                                                          |
| -        | 1.95±0.01ms                                     | 1.67±0.02ms                                  |    0.86 | frame_methods.Fillna.time_bfill(False, 'Int64')                                                                                                                         |
| -        | 1.76±0.05ms                                     | 1.51±0.07ms                                  |    0.86 | frame_methods.Fillna.time_ffill(True, 'Int64')                                                                                                                          |
| -        | 231±7ns                                         | 199±3ns                                      |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_decr', True, 100000)                |
| -        | 238±6ns                                         | 205±0.5ns                                    |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_decr', True, 2000000)               |
| -        | 220±4ns                                         | 190±1ns                                      |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_decr', True, 100000)                |
| -        | 222±5ns                                         | 191±0.4ns                                    |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'non_monotonic', True, 100000)                 |
| -        | 224±5ns                                         | 193±0.3ns                                    |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_decr', True, 2000000)                   |
| -        | 212±5ns                                         | 183±1ns                                      |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_incr', True, 100000)                    |
| -        | 242±5ns                                         | 208±1ns                                      |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'non_monotonic', True, 100000)     |
| -        | 232±3ns                                         | 200±2ns                                      |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_decr', True, 2000000)   |
| -        | 229±1ns                                         | 197±0.7ns                                    |    0.86 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_incr', True, 100000)    |
| -        | 227±5ns                                         | 196±0.8ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_incr', True, 100000)              |
| -        | 227±5ns                                         | 195±2ns                                      |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'non_monotonic', True, 100000)               |
| -        | 231±7ns                                         | 199±2ns                                      |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'non_monotonic', True, 2000000)              |
| -        | 219±5ns                                         | 188±0.6ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_incr', True, 100000)              |
| -        | 227±6ns                                         | 194±0.7ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'non_monotonic', True, 2000000)              |
| -        | 217±4ns                                         | 188±0.5ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_decr', True, 100000)                  |
| -        | 232±6ns                                         | 199±0.8ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_decr', True, 100000)  |
| -        | 230±3ns                                         | 197±0.6ns                                    |    0.86 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'non_monotonic', True, 2000000)  |
| -        | 14.3±0.07ms                                     | 12.3±0.1ms                                   |    0.86 | strings.Contains.time_contains('str', True)                                                                                                                             |
| -        | 14.6±0.08ms                                     | 12.6±0.08ms                                  |    0.86 | strings.Methods.time_get('str')                                                                                                                                         |
| -        | 13.6±0.09ms                                     | 11.7±0.2ms                                   |    0.86 | strings.Methods.time_match('string[python]')                                                                                                                            |
| -        | 10.6±0.03ms                                     | 9.12±0.02ms                                  |    0.86 | strings.Methods.time_normalize('string[python]')                                                                                                                        |
| -        | 11.0±0.04ms                                     | 9.47±0.01ms                                  |    0.86 | strings.Methods.time_startswith('str')                                                                                                                                  |
| -        | 1.38±0.01ms                                     | 1.18±0ms                                     |    0.86 | timeseries.AsOf.time_asof_nan_single('Series')                                                                                                                          |
| -        | 3.60±0.1μs                                      | 3.10±0.02μs                                  |    0.86 | timeseries.AsOf.time_asof_single_early('Series')                                                                                                                        |
| -        | 4.14±0.2μs                                      | 3.57±0.07μs                                  |    0.86 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<MonthBegin>)                                                                                                  |
| -        | 121±3ns                                         | 104±0.3ns                                    |    0.86 | tslibs.timestamp.TimestampProperties.time_tz(None)                                                                                                                      |
| -        | 120±0.9ns                                       | 103±1ns                                      |    0.86 | tslibs.timestamp.TimestampProperties.time_tz(datetime.timezone.utc)                                                                                                     |
| -        | 119±1ns                                         | 102±0.1ns                                    |    0.86 | tslibs.timestamp.TimestampProperties.time_tz(tzfile('/usr/share/zoneinfo/Asia/Tokyo'))                                                                                  |
| -        | 95.0±5μs                                        | 81.9±0.9μs                                   |    0.86 | tslibs.tz_convert.TimeTZConvert.time_tz_convert_from_utc(10000, <DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                       |
| -        | 589±5ns                                         | 507±0.7ns                                    |    0.86 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(0, datetime.timezone(datetime.timedelta(seconds=3600)))                                                         |
| -        | 593±10ns                                        | 508±4ns                                      |    0.86 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(0, tzfile('/usr/share/zoneinfo/Asia/Tokyo'))                                                                    |
| -        | 231±6ns                                         | 195±3ns                                      |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_incr', True, 100000)                |
| -        | 226±5ns                                         | 192±0.9ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_decr', True, 2000000)               |
| -        | 223±5ns                                         | 190±0.5ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_incr', True, 100000)                |
| -        | 241±6ns                                         | 204±0.3ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_decr', True, 2000000)   |
| -        | 243±5ns                                         | 207±0.7ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_incr', True, 100000)    |
| -        | 233±5ns                                         | 197±0.5ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'monotonic_decr', True, 100000)    |
| -        | 229±5ns                                         | 194±0.6ns                                    |    0.85 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'non_monotonic', True, 100000)         |
| -        | 219±3ns                                         | 186±0.6ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_decr', True, 100000)              |
| -        | 225±4ns                                         | 191±0.5ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_decr', True, 2000000)             |
| -        | 221±4ns                                         | 188±0.6ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'non_monotonic', True, 100000)               |
| -        | 212±7ns                                         | 181±0.5ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_incr', True, 100000)                  |
| -        | 237±3ns                                         | 201±0.4ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'non_monotonic', True, 100000)   |
| -        | 230±5ns                                         | 196±0.7ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_decr', True, 100000)  |
| -        | 234±3ns                                         | 198±2ns                                      |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_decr', True, 2000000) |
| -        | 227±4ns                                         | 193±0.6ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'monotonic_incr', True, 100000)  |
| -        | 230±5ns                                         | 195±2ns                                      |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float64Engine'>, <class 'numpy.float64'>), 'non_monotonic', True, 100000)   |
| -        | 228±4ns                                         | 193±0.7ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_decr', True, 100000)      |
| -        | 233±6ns                                         | 198±0.6ns                                    |    0.85 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'non_monotonic', True, 2000000)      |
| -        | 1.52±0s                                         | 1.28±0.01s                                   |    0.85 | reshape.Cut.time_cut_interval(1000)                                                                                                                                     |
| -        | 10.2±0.01ms                                     | 8.64±0.02ms                                  |    0.85 | strings.Methods.time_endswith('string[python]')                                                                                                                         |
| -        | 7.73±0.1ms                                      | 6.54±0.08ms                                  |    0.85 | strings.Methods.time_lower('str')                                                                                                                                       |
| -        | 9.98±0.04ms                                     | 8.53±0.07ms                                  |    0.85 | strings.Methods.time_replace('str')                                                                                                                                     |
| -        | 10.2±0.07ms                                     | 8.74±0.06ms                                  |    0.85 | strings.Methods.time_replace('string[python]')                                                                                                                          |
| -        | 10.9±0.1ms                                      | 9.27±0.09ms                                  |    0.85 | strings.Methods.time_slice('str')                                                                                                                                       |
| -        | 9.02±0.09ms                                     | 7.67±0.05ms                                  |    0.85 | strings.Methods.time_startswith('string[python]')                                                                                                                       |
| -        | 69.1±2ms                                        | 58.6±0.2ms                                   |    0.85 | strings.Slice.time_vector_slice                                                                                                                                         |
| -        | 4.23±0.1μs                                      | 3.58±0.06μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BusinessMonthBegin>)                                                                                          |
| -        | 4.23±0.1μs                                      | 3.59±0.08μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BusinessMonthEnd>)                                                                                            |
| -        | 4.39±0.07μs                                     | 3.73±0.08μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<BusinessQuarterBegin: startingMonth=3>)                                                                       |
| -        | 2.26±0.07μs                                     | 1.91±0.03μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<Day>)                                                                                                         |
| -        | 4.22±0.1μs                                      | 3.57±0.09μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<MonthEnd>)                                                                                                    |
| -        | 4.34±0.08μs                                     | 3.68±0.05μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<QuarterBegin: startingMonth=3>)                                                                               |
| -        | 4.35±0.09μs                                     | 3.70±0.08μs                                  |    0.85 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<QuarterEnd: startingMonth=3>)                                                                                 |
| -        | 521±7ns                                         | 444±1ns                                      |    0.85 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(0, datetime.timezone.utc)                                                                                       |
| -        | 599±9ns                                         | 508±2ns                                      |    0.85 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(0, tzlocal())                                                                                                   |
| -        | 291±10μs                                        | 243±7μs                                      |    0.84 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.int64'>, 2, <built-in function eq>)                                                               |
| -        | 1.28±0.01μs                                     | 1.08±0.01μs                                  |    0.84 | categoricals.CategoricalSlicing.time_getitem_slice('non_monotonic')                                                                                                     |
| -        | 1.77±0.01ms                                     | 1.48±0.01ms                                  |    0.84 | frame_ctor.FromArrays.time_frame_from_arrays_int                                                                                                                        |
| -        | 232±5ns                                         | 195±0.6ns                                    |    0.84 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'non_monotonic', True, 100000)                 |
| -        | 221±2ns                                         | 185±0.7ns                                    |    0.84 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_decr', True, 2000000)                   |
| -        | 235±7ns                                         | 197±1ns                                      |    0.84 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat64Engine'>, 'Float64'), 'non_monotonic', True, 100000)     |
| -        | 230±4ns                                         | 193±0.9ns                                    |    0.84 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_decr', True, 100000)        |
| -        | 230±4ns                                         | 193±0.6ns                                    |    0.84 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_incr', True, 100000)        |
| -        | 220±5ns                                         | 185±0.4ns                                    |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_decr', True, 2000000)                 |
| -        | 210±6ns                                         | 176±2ns                                      |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_incr', True, 100000)                  |
| -        | 241±3ns                                         | 202±0.9ns                                    |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'non_monotonic', True, 2000000)  |
| -        | 233±5ns                                         | 196±0.8ns                                    |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_decr', True, 2000000)     |
| -        | 231±4ns                                         | 194±2ns                                      |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'monotonic_incr', True, 100000)      |
| -        | 229±6ns                                         | 192±0.8ns                                    |    0.84 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int64Engine'>, <class 'numpy.int64'>), 'non_monotonic', True, 100000)       |
| -        | 19.0±2μs                                        | 16.0±0.4μs                                   |    0.84 | period.DataFramePeriodColumn.time_setitem_period_column                                                                                                                 |
| -        | 8.24±0.09ms                                     | 6.92±0.1ms                                   |    0.84 | strings.Methods.time_lower('string[python]')                                                                                                                            |
| -        | 7.95±0.3ms                                      | 6.66±0.2ms                                   |    0.84 | strings.Methods.time_lstrip('str')                                                                                                                                      |
| -        | 8.34±0.1ms                                      | 6.99±0.2ms                                   |    0.84 | strings.Methods.time_lstrip('string[python]')                                                                                                                           |
| -        | 11.8±0.2ms                                      | 9.89±0.2ms                                   |    0.84 | strings.Methods.time_slice('string[python]')                                                                                                                            |
| -        | 104±9μs                                         | 87.6±0.3μs                                   |    0.84 | tslibs.normalize.Normalize.time_normalize_i8_timestamps(10000, <DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>)                                                        |
| -        | 4.26±0.1μs                                      | 3.58±0.06μs                                  |    0.84 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<SemiMonthBegin: day_of_month=15>)                                                                             |
| -        | 4.30±0.2μs                                      | 3.62±0.08μs                                  |    0.84 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<SemiMonthEnd: day_of_month=15>)                                                                               |
| -        | 531±3ns                                         | 446±7ns                                      |    0.84 | tslibs.tz_convert.TimeTZConvert.time_tz_localize_to_utc(100, datetime.timezone.utc)                                                                                     |
| -        | 1.30±0.01μs                                     | 1.08±0.01μs                                  |    0.83 | categoricals.CategoricalSlicing.time_getitem_slice('monotonic_decr')                                                                                                    |
| -        | 13.8±0.05μs                                     | 11.4±0.02μs                                  |    0.83 | categoricals.IsMonotonic.time_categorical_series_is_monotonic_decreasing                                                                                                |
| -        | 13.8±0.03μs                                     | 11.4±0.02μs                                  |    0.83 | categoricals.IsMonotonic.time_categorical_series_is_monotonic_increasing                                                                                                |
| -        | 136±0.8μs                                       | 112±0.4μs                                    |    0.83 | index_cached_properties.IndexCache.time_is_monotonic_increasing('UInt64Index')                                                                                          |
| -        | 210±4ns                                         | 175±0.8ns                                    |    0.83 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_incr', True, 100000)                    |
| -        | 215±5ns                                         | 178±0.1ns                                    |    0.83 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'non_monotonic', True, 100000)                     |
| -        | 238±9ns                                         | 198±0.5ns                                    |    0.83 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedFloat32Engine'>, 'Float32'), 'monotonic_decr', True, 100000)    |
| -        | 235±5ns                                         | 196±1ns                                      |    0.83 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt64Engine'>, 'Int64'), 'monotonic_decr', True, 2000000)       |
| -        | 217±1ns                                         | 179±0.3ns                                    |    0.83 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'non_monotonic', True, 100000)                   |
| -        | 242±0.4ns                                       | 201±0.9ns                                    |    0.83 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Float32Engine'>, <class 'numpy.float32'>), 'monotonic_incr', True, 100000)  |
| -        | 230±5ns                                         | 190±0.4ns                                    |    0.83 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_decr', True, 2000000)     |
| -        | 206±2ns                                         | 171±2ns                                      |    0.83 | libs.InferDtype.time_infer_dtype('np-null')                                                                                                                             |
| -        | 1.34±0ms                                        | 1.12±0.01ms                                  |    0.83 | strftime.BusinessHourStrftime.time_frame_offset_str(1000)                                                                                                               |
| -        | 13.0±0.09ms                                     | 10.8±0.05ms                                  |    0.83 | strftime.BusinessHourStrftime.time_frame_offset_str(10000)                                                                                                              |
| -        | 6.72±0.02ms                                     | 5.58±0.2ms                                   |    0.83 | strings.Contains.time_contains('string[python]', False)                                                                                                                 |
| -        | 9.14±0.08ms                                     | 7.57±0.01ms                                  |    0.83 | strings.Methods.time_isalnum('str')                                                                                                                                     |
| -        | 8.26±0.2ms                                      | 6.87±0.01ms                                  |    0.83 | strings.Methods.time_rstrip('string[python]')                                                                                                                           |
| -        | 8.37±0.1ms                                      | 6.92±0.01ms                                  |    0.83 | strings.Methods.time_strip('string[python]')                                                                                                                            |
| -        | 7.92±0.01ms                                     | 6.60±0.03ms                                  |    0.83 | strings.Methods.time_zfill('string[python]')                                                                                                                            |
| -        | 9.94±0.02μs                                     | 8.22±1μs                                     |    0.83 | timeseries.TzLocalize.time_infer_dst(None)                                                                                                                              |
| -        | 714±4ns                                         | 594±40ns                                     |    0.83 | tslibs.offsets.OnOffset.time_on_offset(<DateOffset: days=2, months=2>)                                                                                                  |
| -        | 128±7μs                                         | 105±1μs                                      |    0.82 | algos.isin.IsIn.time_isin_categorical('uint64')                                                                                                                         |
| -        | 438±5μs                                         | 360±30μs                                     |    0.82 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.int64'>, 3.0, <built-in function gt>)                                                             |
| -        | 1.29±0.01μs                                     | 1.06±0.01μs                                  |    0.82 | categoricals.CategoricalSlicing.time_getitem_slice('monotonic_incr')                                                                                                    |
| -        | 137±1μs                                         | 112±0.4μs                                    |    0.82 | index_cached_properties.IndexCache.time_is_monotonic_decreasing('UInt64Index')                                                                                          |
| -        | 10.5±0.2ms                                      | 8.63±0.1ms                                   |    0.82 | index_object.SetOperations.time_operation('monotonic', 'strings', 'intersection')                                                                                       |
| -        | 216±6ns                                         | 178±1ns                                      |    0.82 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_decr', True, 100000)                    |
| -        | 230±4ns                                         | 188±1ns                                      |    0.82 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_decr', True, 2000000)       |
| -        | 217±5ns                                         | 178±0.3ns                                    |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_decr', True, 100000)                  |
| -        | 224±9ns                                         | 184±0.4ns                                    |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'non_monotonic', True, 2000000)                  |
| -        | 224±6ns                                         | 183±1ns                                      |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_decr', True, 100000)      |
| -        | 222±6ns                                         | 183±0.4ns                                    |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'monotonic_incr', True, 100000)      |
| -        | 223±6ns                                         | 182±0.5ns                                    |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'non_monotonic', True, 100000)       |
| -        | 230±5ns                                         | 188±0.3ns                                    |    0.82 | indexing_engines.NumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.Int32Engine'>, <class 'numpy.int32'>), 'non_monotonic', True, 2000000)      |
| -        | 26.7±0.8ms                                      | 21.9±0.7ms                                   |    0.82 | io.parsers.DoesStringLookLikeDatetime.time_check_datetimes('0.0')                                                                                                       |
| -        | 34.7±1ms                                        | 28.5±1ms                                     |    0.82 | io.parsers.DoesStringLookLikeDatetime.time_check_datetimes('2Q2005')                                                                                                    |
| -        | 1.33±0.01ms                                     | 1.09±0ms                                     |    0.82 | strftime.BusinessHourStrftime.time_frame_offset_repr(1000)                                                                                                              |
| -        | 12.8±0.08ms                                     | 10.5±0.05ms                                  |    0.82 | strftime.BusinessHourStrftime.time_frame_offset_repr(10000)                                                                                                             |
| -        | 7.93±0.05ms                                     | 6.52±0.05ms                                  |    0.82 | strings.Methods.time_istitle('str')                                                                                                                                     |
| -        | 10.7±0.08ms                                     | 8.82±0.04ms                                  |    0.82 | strings.Methods.time_normalize('str')                                                                                                                                   |
| -        | 7.98±0.2ms                                      | 6.57±0.01ms                                  |    0.82 | strings.Methods.time_strip('str')                                                                                                                                       |
| -        | 9.91±0.2ms                                      | 8.14±0.2ms                                   |    0.82 | strings.Methods.time_zfill('string[pyarrow]')                                                                                                                           |
| -        | 225±6ns                                         | 181±1ns                                      |    0.81 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_decr', True, 100000)        |
| -        | 224±5ns                                         | 181±0.4ns                                    |    0.81 | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'monotonic_incr', True, 100000)        |
| -        | 205±0.7ns                                       | 166±2ns                                      |    0.81 | libs.InferDtype.time_infer_dtype('np-floating')                                                                                                                         |
| -        | 7.72±0.2ms                                      | 6.26±0.02ms                                  |    0.81 | strings.Methods.time_zfill('str')                                                                                                                                       |
| -        | 225±5ns                                         | 180±0.8ns                                    |    0.8  | indexing_engines.MaskedNumericEngineIndexing.time_get_loc_near_middle((<class 'pandas._libs.index.MaskedInt32Engine'>, 'Int32'), 'non_monotonic', True, 100000)         |
| -        | 207±2ns                                         | 165±0.5ns                                    |    0.8  | libs.InferDtype.time_infer_dtype('np-int')                                                                                                                              |
| -        | 207±0.4ns                                       | 166±1ns                                      |    0.8  | libs.InferDtype.time_infer_dtype_skipna('np-floating')                                                                                                                  |
| -        | 207±2ns                                         | 165±1ns                                      |    0.8  | libs.InferDtype.time_infer_dtype_skipna('np-int')                                                                                                                       |
| -        | 206±2ns                                         | 165±1ns                                      |    0.8  | libs.InferDtype.time_infer_dtype_skipna('np-null')                                                                                                                      |
| -        | 8.83±0.02ms                                     | 7.08±0.03ms                                  |    0.8  | strings.Contains.time_contains('str', False)                                                                                                                            |
| -        | 7.53±0.05ms                                     | 6.04±0.01ms                                  |    0.8  | strings.Methods.time_isalnum('string[python]')                                                                                                                          |
| -        | 7.73±0.04ms                                     | 6.19±0.05ms                                  |    0.8  | strings.Methods.time_isupper('str')                                                                                                                                     |
| -        | 7.77±0.07ms                                     | 6.13±0.07ms                                  |    0.79 | strings.Methods.time_isalpha('str')                                                                                                                                     |
| -        | 7.64±0.09ms                                     | 6.06±0.02ms                                  |    0.79 | strings.Methods.time_islower('str')                                                                                                                                     |
| -        | 6.30±0.03ms                                     | 4.97±0.02ms                                  |    0.79 | strings.Methods.time_istitle('string[python]')                                                                                                                          |
| -        | 12.3±0.05ms                                     | 9.80±0.1ms                                   |    0.79 | strings.Methods.time_upper('string[python]')                                                                                                                            |
| -        | 920±40μs                                        | 720±60μs                                     |    0.78 | arithmetic.IntFrameWithScalar.time_frame_op_with_scalar(<class 'numpy.int64'>, 2, <built-in function truediv>)                                                          |
| -        | 8.43±0.5ms                                      | 6.55±0.03ms                                  |    0.78 | strings.Methods.time_rstrip('str')                                                                                                                                      |
| -        | 612±8ns                                         | 475±1ns                                      |    0.78 | tslibs.offsets.OnOffset.time_on_offset(<Day>)                                                                                                                           |
| -        | 246±6μs                                         | 188±0.8μs                                    |    0.77 | algos.isin.IsInForObjects.time_isin('nans', 'nans')                                                                                                                     |
| -        | 5.93±0.01ms                                     | 4.59±0.02ms                                  |    0.77 | strings.Methods.time_isupper('string[python]')                                                                                                                          |
| -        | 12.2±0.04ms                                     | 9.42±0.09ms                                  |    0.77 | strings.Methods.time_upper('str')                                                                                                                                       |
| -        | 1.05±0.01μs                                     | 803±3ns                                      |    0.77 | tslibs.timestamp.TimestampConstruction.time_parse_now                                                                                                                   |
| -        | 6.37±0.07ms                                     | 4.84±0.05ms                                  |    0.76 | strings.Methods.time_isdecimal('str')                                                                                                                                   |
| -        | 6.37±0.1ms                                      | 4.84±0.05ms                                  |    0.76 | strings.Methods.time_isdigit('str')                                                                                                                                     |
| -        | 5.99±0.06ms                                     | 4.57±0.01ms                                  |    0.76 | strings.Methods.time_islower('string[python]')                                                                                                                          |
| -        | 5.93±0.02ms                                     | 4.50±0.04ms                                  |    0.76 | strings.Methods.time_isspace('str')                                                                                                                                     |
| -        | 5.94±0.02ms                                     | 4.47±0.01ms                                  |    0.75 | strings.Methods.time_isalpha('string[python]')                                                                                                                          |
| -        | 6.44±0.09ms                                     | 4.79±0.01ms                                  |    0.74 | strings.Methods.time_isnumeric('str')                                                                                                                                   |
| -        | 1.10±0.01μs                                     | 808±6ns                                      |    0.74 | tslibs.timestamp.TimestampConstruction.time_parse_today                                                                                                                 |
| -        | 11.2±0.05μs                                     | 8.19±0.1μs                                   |    0.73 | timeseries.TzLocalize.time_infer_dst('UTC')                                                                                                                             |
| -        | 12.6±0.3μs                                      | 9.19±0.07μs                                  |    0.73 | tslibs.offsets.OffestDatetimeArithmetic.time_add(<DateOffset: days=2, months=2>)                                                                                        |
| -        | 869±3ns                                         | 636±2ns                                      |    0.73 | tslibs.timestamp.TimestampConstruction.time_parse_iso8601_no_tz                                                                                                         |
| -        | 25.5±1ms                                        | 18.3±0.6ms                                   |    0.72 | reindex.Reindex.time_reindex_multiindex_no_cache                                                                                                                        |
| -        | 13.6±0.2μs                                      | 9.78±0.1μs                                   |    0.72 | tslibs.offsets.OffestDatetimeArithmetic.time_add_np_dt64(<DateOffset: days=2, months=2>)                                                                                |
| -        | 165±7μs                                         | 117±3μs                                      |    0.71 | algos.isin.IsInForObjects.time_isin('short', 'nans')                                                                                                                    |
| -        | 4.72±0.08ms                                     | 3.34±0.02ms                                  |    0.71 | strings.Methods.time_isdecimal('string[python]')                                                                                                                        |
| -        | 4.67±0.01ms                                     | 3.34±0.01ms                                  |    0.71 | strings.Methods.time_isnumeric('string[python]')                                                                                                                        |
| -        | 2.04±0.02μs                                     | 1.45±0μs                                     |    0.71 | tslibs.offsets.OnOffset.time_on_offset(<BusinessMonthEnd>)                                                                                                              |
| -        | 22.0±0.1ms                                      | 15.1±0.04ms                                  |    0.69 | frame_methods.Fillna.time_bfill(True, 'object')                                                                                                                         |
| -        | 4.85±0.05ms                                     | 3.35±0.01ms                                  |    0.69 | strings.Methods.time_isdigit('string[python]')                                                                                                                          |
| -        | 4.39±0.03ms                                     | 3.05±0.01ms                                  |    0.69 | strings.Methods.time_isspace('string[python]')                                                                                                                          |
| -        | 1.97±0.01μs                                     | 1.37±0μs                                     |    0.69 | tslibs.offsets.OnOffset.time_on_offset(<BusinessMonthBegin>)                                                                                                            |
| -        | 562±10ms                                        | 383±3ms                                      |    0.68 | reshape.Cut.time_cut_interval(10)                                                                                                                                       |
| -        | 556±10ms                                        | 380±5ms                                      |    0.68 | reshape.Cut.time_cut_interval(4)                                                                                                                                        |
| -        | 22.4±0.8μs                                      | 15.2±0.3μs                                   |    0.68 | tslibs.offsets.OffestDatetimeArithmetic.time_add_10(<DateOffset: days=2, months=2>)                                                                                     |
| -        | 1.82±0μs                                        | 1.25±0μs                                     |    0.68 | tslibs.offsets.OnOffset.time_on_offset(<MonthEnd>)                                                                                                                      |
| -        | 725±8ns                                         | 490±2ns                                      |    0.68 | tslibs.timestamp.TimestampConstruction.time_from_npdatetime64                                                                                                           |
| -        | 22.4±0.2μs                                      | 15.0±0.08μs                                  |    0.67 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract(<DateOffset: days=2, months=2>)                                                                                   |
| -        | 31.2±0.1μs                                      | 20.5±0.4μs                                   |    0.66 | tslibs.offsets.OffestDatetimeArithmetic.time_subtract_10(<DateOffset: days=2, months=2>)                                                                                |
| -        | 1.75±0.03μs                                     | 1.16±0μs                                     |    0.66 | tslibs.offsets.OnOffset.time_on_offset(<MonthBegin>)                                                                                                                    |
| -        | 1.39±0.01μs                                     | 827±6ns                                      |    0.6  | tslibs.offsets.OnOffset.time_on_offset(<BYearEnd: month=12>)                                                                                                            |
| -        | 860±20ns                                        | 499±8ns                                      |    0.58 | tslibs.offsets.OnOffset.time_on_offset(<BYearBegin: month=1>)                                                                                                           |
| -        | 1.32±0.01μs                                     | 755±3ns                                      |    0.57 | tslibs.offsets.OnOffset.time_on_offset(<YearEnd: month=12>)                                                                                                             |
| -        | 1.55±0.01μs                                     | 867±6ns                                      |    0.56 | tslibs.offsets.OnOffset.time_on_offset(<BusinessQuarterEnd: startingMonth=3>)                                                                                           |
| -        | 894±8ns                                         | 497±2ns                                      |    0.56 | tslibs.offsets.OnOffset.time_on_offset(<SemiMonthBegin: day_of_month=15>)                                                                                               |
| -        | 865±8ns                                         | 478±8ns                                      |    0.55 | tslibs.offsets.OnOffset.time_on_offset(<YearBegin: month=1>)                                                                                                            |
| -        | 1.50±0.03μs                                     | 796±8ns                                      |    0.53 | tslibs.offsets.OnOffset.time_on_offset(<BusinessQuarterBegin: startingMonth=3>)                                                                                         |
| -        | 1.45±0.01μs                                     | 766±20ns                                     |    0.53 | tslibs.offsets.OnOffset.time_on_offset(<QuarterEnd: startingMonth=3>)                                                                                                   |
| -        | 1.45±0μs                                        | 725±2ns                                      |    0.5  | tslibs.offsets.OnOffset.time_on_offset(<QuarterBegin: startingMonth=3>)                                                                                                 |
| -        | 1.44±0.05μs                                     | 527±7ns                                      |    0.37 | tslibs.offsets.OnOffset.time_on_offset(<SemiMonthEnd: day_of_month=15>)                                                                                                 |
| -        | 318±4ns                                         | 112±0.7ns                                    |    0.35 | libs.ScalarListLike.time_is_scalar({0: 1})                                                                                                                              |
| -        | 318±1ns                                         | 112±0.3ns                                    |    0.35 | libs.ScalarListLike.time_is_scalar({1, 2, 3})                                                                                                                           |
| -        | 1.79±0.02μs                                     | 561±6ns                                      |    0.31 | index_object.IntervalIndexMethod.time_monotonic_inc(1000)                                                                                                               |
| -        | 1.87±0.02μs                                     | 576±7ns                                      |    0.31 | index_object.IntervalIndexMethod.time_monotonic_inc(100000)                                                                                                             |
| -        | 279±0.4ns                                       | 79.7±0.8ns                                   |    0.29 | libs.ScalarListLike.time_is_list_like(<NA>)                                                                                                                             |
| -        | 284±0.6ns                                       | 81.7±0.9ns                                   |    0.29 | libs.ScalarListLike.time_is_list_like(NaT)                                                                                                                              |
| -        | 282±0.4ns                                       | 79.9±0.1ns                                   |    0.28 | libs.ScalarListLike.time_is_list_like((1+2j))                                                                                                                           |
| -        | 284±2ns                                         | 80.6±0.6ns                                   |    0.28 | libs.ScalarListLike.time_is_list_like(0)                                                                                                                                |
| -        | 283±1ns                                         | 80.0±0.2ns                                   |    0.28 | libs.ScalarListLike.time_is_list_like(1.0)                                                                                                                              |
| -        | 289±0.6ns                                       | 80.8±0.6ns                                   |    0.28 | libs.ScalarListLike.time_is_list_like(None)                                                                                                                             |
| -        | 283±1ns                                         | 79.3±0.6ns                                   |    0.28 | libs.ScalarListLike.time_is_list_like(True)                                                                                                                             |
| -        | 294±3ns                                         | 80.1±0.3ns                                   |    0.27 | libs.ScalarListLike.time_is_list_like(numpy.datetime64('1970-01-01T00:00:00.000000123'))                                                                                |
| -        | 294±1ns                                         | 80.8±0.5ns                                   |    0.27 | libs.ScalarListLike.time_is_list_like(numpy.timedelta64(123,'ns'))

@lukemanley
Copy link
Member

lukemanley commented Sep 17, 2023

Not sure what the best way to approach this is - do we try to handle fixing these in a single branch along with changing to 3.0? Or do we just adopt 3.0 in one PR and try to address the regressions after?

Maybe adopt 3.0 in one PR and create a new issue (tracker issue?) summarizing the regressions? Assuming they can be summarized...

@WillAyd
Copy link
Member

WillAyd commented Sep 18, 2023

Looks like a lot of regressions are in strings.methods. Is there anything in the annotation there that would point to why?

@lithomas1
Copy link
Member

lithomas1 commented Sep 18, 2023

This was already done in #54335.

At the sprint, the consensus was to revert until we could understand why the regressions were happening.
I've been meaning to do this, but haven't had the time since summer ended.

If you have the time to have a look, that'd be great.

scikit-learn also had some issues with perf regressions (I opened an issue there), their problems seem to be GIL related.

@WillAyd
Copy link
Member

WillAyd commented Sep 18, 2023

I did a quick callgrind on the string series constructor showing the most regression. Here are the top 10 functions from Cython 2:

3,300,042,608 (17.84%)  ???:get_item_pointer [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
3,200,052,169 (17.30%)  ???:PyArray_Scalar [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
3,000,289,006 (16.22%)  ???:__pyx_pw_6pandas_5_libs_3lib_33ensure_string_array [/home/willayd/clones/pandas/build/cp310/pandas/_libs/lib.cpython-310-x86_64-linux-gnu.so]
2,800,017,582 (15.14%)  ???:array_item [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
  500,000,000 ( 2.70%)  ???:OBJECT_getitem [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
  272,375,045 ( 1.47%)  /usr/local/src/conda/python-3.10.12/Python/ceval.c:_PyEval_EvalFrameDefault'2 [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]
  221,369,714 ( 1.20%)  /usr/local/src/conda/python-3.10.12/Modules/sre_lib.h:sre_ucs1_match [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]
  221,185,641 ( 1.20%)  /usr/local/src/conda/python-3.10.12/Parser/tokenizer.c:tok_nextc [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]
  163,678,799 ( 0.88%)  /usr/local/src/conda/python-3.10.12/Parser/tokenizer.c:tok_get [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]
  138,241,199 ( 0.75%)  /usr/local/src/conda/python-3.10.12/Python/pyhash.c:siphash24 [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]

Versus with Cython 3:

11,900,079,530 (20.99%)  ???:prepare_index [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
 6,500,003,510 (11.47%)  ???:array_subscript [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
 4,323,588,712 ( 7.63%)  /usr/local/src/conda/python-3.10.12/Objects/obmalloc.c:object_dealloc
 3,598,715,264 ( 6.35%)  ???:__Pyx_GetItemInt_Fast.constprop.0 [/home/willayd/clones/pandas/build/cp310/pandas/_libs/tslibs/dtypes.cpython-310-x86_64-linux-gnu.so]
 3,300,042,608 ( 5.82%)  ???:get_item_pointer [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
 3,200,052,169 ( 5.65%)  ???:PyArray_Scalar [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so]
 2,798,272,572 ( 4.94%)  /usr/local/src/conda/python-3.10.12/Objects/longobject.c:PyLong_FromSsize_t [/home/willayd/mambaforge/envs/pandas-dev/bin/python3.10]
 2,400,016,776 ( 4.23%)  ???:PyArray_PyIntAsIntp_ErrMsg [/home/willayd/mambaforge/envs/pandas-dev/lib/python3.10/site-packages/numpy/core/_multiarray_umath.cpython-310-x86_64-linux-gnu.so
]
 2,398,998,037 ( 4.23%)  /usr/local/src/conda/python-3.10.12/Objects/obmalloc.c:_PyLong_New
 2,200,360,008 ( 3.88%)  ???:__pyx_pw_6pandas_5_libs_3lib_33ensure_string_array [/home/willayd/clones/pandas/build/cp310/pandas/_libs/lib.cpython-310-x86_64-linux-gnu.so]

Interesting to see the prepare_index / array_subscript bottlenecks appear in 3.X

@WillAyd
Copy link
Member

WillAyd commented Sep 18, 2023

At least according to callgrind this patch should help the string methods a good deal:

diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx
index 0c0610f720..b05d9b665e 100644
--- a/pandas/_libs/lib.pyx
+++ b/pandas/_libs/lib.pyx
@@ -776,6 +776,7 @@ cpdef ndarray[object] ensure_string_array(
     cdef:
         Py_ssize_t i = 0, n = len(arr)
         bint already_copied = True
+        ndarray[object] newarr
 
     if hasattr(arr, "to_numpy"):
 
@@ -800,8 +801,9 @@ cpdef ndarray[object] ensure_string_array(
         # short-circuit, all elements are str
         return result
 
+    newarr = arr
     for i in range(n):
-        val = arr[i]
+        val = newarr[i]
 
         if isinstance(val, str):
             continue

I think the Cython3 version is doing a lot of unecessary Python interation because we never explicitly declare arr as an array. This patch makes that more explicit.

@mroeschke mroeschke added the Dependencies Required and optional dependencies label Sep 18, 2023
@jbrockmendel
Copy link
Member

Are the "failed" asvs bc it is slow or raising. The latter seem like theyd be deal-breakers.

@rhshadrach
Copy link
Member Author

rhshadrach commented Sep 18, 2023

Are the "failed" asvs bc it is slow or raising. The latter seem like theyd be deal-breakers.

It is raising. I suspect it is because of this type-hint:

https://github.com/pandas-dev/pandas/blob/025e6ae2e9de9036c0b64f9f6571f00888b9f403/pandas/_libs/tslibs/period.pyx#L2514C5-L2514C6

The ASV in question is passing None. I believe this combine with binding-functions are now the default is giving the error. Not familiar with the code, but a quick glance looks like None should be allowed?

@rhshadrach
Copy link
Member Author

I like @WillAyd's approach - opening separate PRs from this when the adjustments are perf neutral or positive with Cython 0.x. I'm happy to routinely update the benchmarks here as we make progress. I think once we get it whittled down a bit and feel comfortable with any remaining regressions, we can open a tracking issue for the remaining as @lukemanley suggested.

@rhshadrach
Copy link
Member Author

The regressions in the OP have been updated.

@rhshadrach
Copy link
Member Author

While we've made some progress by specifying dtypes for ndarrays, there are a number of places in the code (e.g. map_infer in lib.pyx) that are meant to handle generic ndarrays. It seems like there is a performance regression in this regard with Cython 3.0.

@lithomas1
Copy link
Member

@rhshadrach

If you pull the .pyi changs from #54335, the typing should go green again btw.

@lithomas1
Copy link
Member

@rhshadrach
Are you able to rerun benchmarks from Cython master?

(The linked PR for the GIL stuff was merged for 3.0.3, but 3.0.3 also had issues compiling pandas.)

I just realized that numpy 2.0 is coming out soonish (the RC will be out in December) and we need this for that, so it'd be good to take another look at what's regressed again here before that.

@rhshadrach
Copy link
Member Author

rhshadrach commented Oct 13, 2023

@lithomas1 - it seems like it might be possible, but so far I haven't gotten it to work. We can tell ASV to use pip and I can install the master branch of Cython using

pip install git+https://github.com/cython/cython@master

However, when I use

"Cython": ["pip+git+https://github.com/cython/cython@master"],

in the matrix, I get

ResolvePackageNotFound:
- //github.com/cython/cython@master

I've also tried leaving out git and https:// in the above line, but none are working.

Still, I'm going to try to rerun on 3.0.3, see if I run into the build problems.

@rhshadrach
Copy link
Member Author

@lithomas1 - benchmarks updated; I'm still seeing gil regressions.

@WillAyd
Copy link
Member

WillAyd commented Oct 23, 2023

AFAICT the GIL regression might trace back to how we are using a function pointer to a double converter in our module. Here is what I believe to be the troublesome code:

double (*double_converter)(const char *, char **,

If you look at the generated code for say try_double_nogil in Cython 0.29 versus Cython 3.0, you'll notice the former generates something like:

        /* "pandas/_libs/parsers.pyx":1709
 *                 data[0] = double_converter(word, &p_end, parser.decimal,
 *                                            parser.sci, parser.thousands,
 *                                            1, &error, NULL)             # <<<<<<<<<<<<<<
 *                 if error != 0 or p_end == word or p_end[0]:
 *                     error = 0
 */
        (__pyx_v_data[0]) = __pyx_v_double_converter(__pyx_v_word, (&__pyx_v_p_end), __pyx_v_parser->decimal, __pyx_v_parser->sci, __pyx_v_parser->thousands, 1, (&__pyx_v_error), NULL);

Whereas the latter does

        /* "pandas/_libs/parsers.pyx":1709
 *                 data[0] = double_converter(word, &p_end, parser.decimal,
 *                                            parser.sci, parser.thousands,
 *                                            1, &error, NULL)             # <<<<<<<<<<<<<<
 *                 if error != 0 or p_end == word or p_end[0]:
 *                     error = 0
 */
        __pyx_t_6 = __pyx_v_double_converter(__pyx_v_word, (&__pyx_v_p_end), __pyx_v_parser->decimal, __pyx_v_parser->sci, __pyx_v_parser->thousands, 1, (&__pyx_v_error), NULL); if (unlikely(__Pyx_ErrOccurredWithGIL())) __PYX_ERR(0, 1707, __pyx_L1_error)

I'm guessing that the latter is affected by the changes to nogil and noexcept that occurred with Cython 3, although changing the troublesome declaration to noexcept nogil does not change what gets generated

@WillAyd
Copy link
Member

WillAyd commented Oct 23, 2023

Hard to make an MRE for Cython though. Even this generates the proper code with 3.0.4:

cdef extern from "string.h":
    int strcmp(const char* s1, const char* s2) nogil

cdef int compares_foo() nogil:
    return strcmp("foo", "foo")

cdef int compares_foo_noexcept() noexcept nogil:
    return strcmp("foo", "foo")

ctypedef struct foo_t:
    int (*fnptr)() noexcept nogil

def main():
    print(compares_foo())
    print(compares_foo_noexcept())
    cdef foo_t foo
    foo.fnptr = compares_foo_noexcept
    print(foo.fnptr())    
    

if __name__ == "__main__":
    main()

yields:

  /* "cython_repo.pyx":17
 *     print(compares_foo_noexcept())
 *     cdef foo_t foo
 *     foo.fnptr = compares_foo_noexcept             # <<<<<<<<<<<<<<
 *     print(foo.fnptr())
 * 
 */
  __pyx_v_foo.fnptr = __pyx_f_11cython_repo_compares_foo_noexcept;

  /* "cython_repo.pyx":18
 *     cdef foo_t foo
 *     foo.fnptr = compares_foo_noexcept
 *     print(foo.fnptr())             # <<<<<<<<<<<<<<
 * 
 * 
 */
  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_foo.fnptr()); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

So the issue seems really specific to our parser code

@WillAyd
Copy link
Member

WillAyd commented Nov 8, 2023

Ah wow that's a great find. Let me see if I can boil that down to an MRE and will report upstream. Thanks a ton @seberg !

@seberg
Copy link
Contributor

seberg commented Nov 8, 2023

Yeah, I linked it. It is intentional, so not sure if NumPy could short-cut a bit earlier, although you still have a few more layers either way.

@seberg
Copy link
Contributor

seberg commented Nov 8, 2023

Cython 3, although changing the troublesome declaration to noexcept nogil does not change what gets generated

Old issue, but did you also change the signature that is part of the function signature itself? The linked one wouldn't be the one used in the example.

@WillAyd
Copy link
Member

WillAyd commented Nov 8, 2023

That was exactly the problem - well spotted

@rhshadrach
Copy link
Member Author

@lithomas1

Do you mind syncing in my .pyi file changes from #54335? This should get code checks to green. I can also push to your branch if you'd like.

Done.

Also, are the benchmarks updated with #55736 merged?

Yes - I'm not sure why the series_methods benchmarks are still showing regressions.

@rhshadrach
Copy link
Member Author

Performance regressions and enhancements have been updated. Looks like the series_methods were False positives, they mostly seem to have disappeared. Nice job on #55915 @WillAyd - indexing is mostly gone as well.

I think we're getting very close to being able to write the rest up as issues, if we aren't already there.

@WillAyd
Copy link
Member

WillAyd commented Nov 13, 2023

IMO the benefit of the performance increases outweigh the regressions at this point, so I would be +1 to move forward with this and move regressions to a separate issue

@rhshadrach
Copy link
Member Author

series_methods.Fillna are back, but last time I tried to reproduce them locally I wasn't able to. I suspect they might be false positives.

@lithomas1
Copy link
Member

I think it's time we put this in now.

We can't compile against the nightly numpys anymore on Windows because of a bug in old Cython.

@rhshadrach Can you merge in main to fix the docs?

It also looks like a few more stubs fell out of date since the last time I fixed them.

@rhshadrach
Copy link
Member Author

rhshadrach commented Nov 14, 2023

@rhshadrach Can you merge in main to fix the docs?

It also looks like a few more stubs fell out of date since the last time I fixed them.

@lithomas1 - done. I thought I had pushed my change to Cython 3.0.5, but I've apparently been running ASVs with 3.0.4 most recently. I think this may be why I can't reproduce regressions locally (been compiling with 3.0.5). I'd like to do one more full ASV run tonight before merging.

@rhshadrach
Copy link
Member Author

@lithomas1 - benchmarks posted, no significant changes. Good to merge on my end. I did open cython/cython#5821 because when I go to profile the regression it disappears.

Copy link
Member

@lithomas1 lithomas1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. This LGTM.

I fixed a typo (the version in pyproject.toml was "3.0.4" which I changed to "3.0.5").
I'll merge when that change become green.

@lithomas1 lithomas1 merged commit e5301a8 into pandas-dev:main Nov 16, 2023
@lithomas1
Copy link
Member

thanks @rhshadrach

@jbrockmendel
Copy link
Member

nice!

@rhshadrach
Copy link
Member Author

And thanks @WillAyd for all the help on fixing regressions!

@rhshadrach rhshadrach deleted the unpin_cython_everywhere branch November 16, 2023 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Dependencies Required and optional dependencies
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants