Skip to content

PERF: Regressions since 0.20.3 #17861

@TomAugspurger

Description

@TomAugspurger
Contributor

These are fairly reproducible on my machine:

       before           after         ratio
     [eac4d3f7]       [92db5c9c]
+           396μs            746μs     1.88  inference.DtypeInfer.time_uint32
+     2.63±0.02ms       3.93±0.1ms     1.49  indexing.IndexingMethods.time_take_dtindex
+     2.64±0.06ms      3.83±0.06ms     1.45  indexing.IndexingMethods.time_take_intindex
       before           after         ratio
     [eac4d3f7]       [92db5c9c]
+     1.43±0.01ms      1.74±0.07ms     1.22  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BDay', 1)
+     1.56±0.02ms      1.74±0.07ms     1.12  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('MonthBegin', 2)
+          56.0ms           61.8ms     1.10  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253Quarter_2', 2)

Activity

added this to the 0.21.0 milestone on Oct 13, 2017
jreback

jreback commented on Oct 14, 2017

@jreback
Contributor

cc @jbrockmendel if u have any ideas here

jbrockmendel

jbrockmendel commented on Oct 15, 2017

@jbrockmendel
Member

I'll take a look at this.

jbrockmendel

jbrockmendel commented on Oct 15, 2017

@jbrockmendel
Member

Best guess is the change in _to_i8 (previously in _libs.index, now in tslib). Old:

cdef inline _to_i8(object val):
    cdef pandas_datetimestruct dts
    try:
        return val.value
    except AttributeError:
        if util.is_datetime64_object(val):
            return get_datetime64_value(val)
        elif PyDateTime_Check(val):
            tzinfo = getattr(val, 'tzinfo', None)
            # Save the original date value so we can get the utcoffset from it.
            ival = _pydatetime_to_dts(val, &dts)
            if tzinfo is not None and not is_utc(tzinfo):
                offset = get_utcoffset(tzinfo, val)
                ival -= tslib._delta_to_nanoseconds(offset)
            return ival
        return val

New:

cdef inline _to_i8(object val):
    cdef pandas_datetimestruct dts
    try:
        return val.value
    except AttributeError:
        if is_datetime64_object(val):
            return get_datetime64_value(val)
        elif PyDateTime_Check(val):
            return Timestamp(val).value
        return val
jbrockmendel

jbrockmendel commented on Oct 15, 2017

@jbrockmendel
Member

Hmm in %timeit reverting this makes a pretty big difference for the ind.get_loc(0) bench, but pretty small (though at least in the right direction) differences for time_take_dtindex and time_take_intindex

jbrockmendel

jbrockmendel commented on Oct 16, 2017

@jbrockmendel
Member

Does asv have something analogous to git bisect?

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

Sorry, those commit hashes in the original post look entirely incorrect... Let me rerun them.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

Updated:

       before           after         ratio
       [888c4ec3]       [36c309ed]
!     4.01±0.02ms           failed      n/a  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('LastWeekOfMonth', 1)
!     4.39±0.01ms           failed      n/a  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('LastWeekOfMonth', 2)
!      9.17±0.1ms           failed      n/a  frame_methods.Formatting.time_frame_repr_wide
!      19.7±0.2ms           failed      n/a  frame_methods.Formatting.time_html_repr_trunc_mi
!      14.4±0.2ms           failed      n/a  frame_methods.Formatting.time_html_repr_trunc_si
!      10.8±0.1ms           failed      n/a  frame_methods.Formatting.time_repr_tall
!         117±2ms           failed      n/a  frame_methods.Formatting.time_to_html_mixed
!      14.1±0.1ms           failed      n/a  frame_methods.Formatting.time_to_string_floats
+      10.3±0.5ms            4.83s   469.35  inference.DtypeInfer.time_timedelta64_2
+     8.94±0.09ms            3.03s   339.45  inference.DtypeInfer.time_datetime64
+      29.8±0.4ms            5.99s   201.19  binary_ops.Timeseries.time_timestamp_ops_diff2
+        80.7±1ms            9.27s   114.89  binary_ops.TimeseriesTZ.time_timestamp_ops_diff2
+     3.36±0.03ms          278±2ms    82.71  timeseries.SeriesArithmetic.time_add_offset_delta
+      60.2±0.4ms            3.91s    64.91  inference.DtypeInfer.time_timedelta64_1
+      9.64±0.2ms          297±5ms    30.83  timeseries.SeriesArithmetic.time_add_offset_fast
+     6.18±0.09ms          122±1ms    19.77  categoricals.Categoricals3.time_rank_string_cat
+      36.6±0.4ms          576±1ms    15.75  packers.packers_read_stata.time_packers_read_stata
+     45.8±0.01ms            616ms    13.44  packers.packers_read_stata_with_validation.time_packers_read_stata_with_validation
+      28.5±0.2ms          308±2ms    10.84  packers.STATA.time_write_stata
+      40.5±0.4ms        323±0.9ms     7.97  packers.STATA.time_write_stata_with_validation
+      34.1±0.4ms          107±1ms     3.15  join_merge.Align.time_series_align_int64_index
+        631±10μs      1.51±0.01ms     2.39  indexing.Int64Indexing.time_getitem_array
+     7.13±0.04ms      16.4±0.09ms     2.30  timeseries.DatetimeIndex.time_infer_freq_none
+     3.62±0.05ms       7.34±0.1ms     2.03  indexing.Int64Indexing.time_getitem_lists
+     2.44±0.04μs      4.25±0.05μs     1.74  indexing.DataFrameIndexing.time_get_value
+         285±6μs         490±10μs     1.72  indexing.Int64Indexing.time_getitem_list_like
+      19.2±0.1ms       30.8±0.8ms     1.60  sparse.sparse_array_constructor.time_sparse_array_constructor_object_non_nan_fill_value_1percent
+      32.2±0.4ms       48.7±0.1ms     1.51  sparse.sparse_array_constructor.time_sparse_array_constructor_object_non_nan_fill_value_10percent
+     2.47±0.03ms      3.72±0.04ms     1.51  indexing.IndexingMethods.time_take_dtindex
+     2.48±0.07ms      3.73±0.03ms     1.50  indexing.IndexingMethods.time_take_intindex
+      6.12±0.1ms      9.04±0.05ms     1.48  binary_ops.Ops2.time_frame_int_div_by_zero
+     5.33±0.01ms      7.65±0.01ms     1.43  timeseries.DatetimeIndex.time_infer_freq_business
+        564±20ms          792±7ms     1.40  timeseries.SeriesArithmetic.time_add_offset_slow
+     2.95±0.09ms      4.05±0.03ms     1.37  strings.StringMethods.time_get
+     2.68±0.02ms      3.66±0.06ms     1.37  period.Algorithms.time_value_counts_pseries
+     2.09±0.03ms      2.87±0.02ms     1.37  period.Algorithms.time_drop_duplicates_pseries
+     6.84±0.07μs       8.89±0.1μs     1.30  timestamp.TimestampOps.time_replace_across_dst
+         252±2ms          322±5ms     1.28  rolling.SeriesRolling.time_rolling_quantile_median_l
+      7.91±0.1μs       10.1±0.1μs     1.28  timestamp.TimestampOps.time_replace_tz
+       252±0.6ms          322±1ms     1.28  rolling.DataframeRolling.time_rolling_quantile_median_l
+     1.25±0.01ms      1.58±0.01ms     1.26  categoricals.Categoricals.time_constructor_datetimes_with_nat
+         1.30±0s            1.61s     1.24  groupby.GroupBySuite.time_unique('float', 10000)
+      10.1±0.2μs       12.5±0.2μs     1.23  timestamp.TimestampProperties.time_is_quarter_end
+         842±4ms          1.02±0s     1.22  groupby.GroupBySuite.time_unique('int', 10000)
+         113±1ms          135±1ms     1.19  rolling.SeriesRolling.time_rolling_quantile_median
+         111±1ms          132±2ms     1.19  rolling.DataframeRolling.time_rolling_quantile_median
+     3.17±0.04ms      3.77±0.05ms     1.19  index_object.SetOperations.time_datetime_difference
+      9.66±0.1ms       11.4±0.1ms     1.18  groupby.GroupBySuite.time_unique('int', 100)
+      35.5±0.5μs       41.5±0.4μs     1.17  indexing.IntervalIndexing.time_getitem_scalar
+      14.5±0.2ms       16.9±0.4ms     1.17  groupby.GroupBySuite.time_unique('float', 100)
+      59.9±0.3ms       69.8±0.3ms     1.17  hdfstore_bench.HDF5.time_write_store_table
+        34.7±1ms       40.3±0.5ms     1.16  strings.StringMethods.time_join_split_expand
+     3.98±0.05ms      4.59±0.05ms     1.15  groupby.Transform.time_transform_ufunc
+         227±2μs          261±6μs     1.15  indexing.MultiIndexing.time_series_xs_mi_ix
+      10.5±0.1μs       12.1±0.2μs     1.15  indexing.Int64Indexing.time_iloc_scalar
+     1.68±0.01ms         1.93±0ms     1.14  indexing.MultiIndexing.time_multiindex_get_indexer
+         251±4μs          287±2μs     1.14  indexing.MultiIndexing.time_multiindex_large_get_loc
+     6.53±0.03μs      7.47±0.07μs     1.14  timestamp.TimestampOps.time_replace_None
+      41.3±0.7μs       46.8±0.5μs     1.13  indexing.Int64Indexing.time_loc_scalar
+      84.1±0.7μs       94.4±0.6μs     1.12  series_methods.series_clip.time_series_dropna_datetime
+           508ms            568ms     1.12  groupby.groupby_multi_index.time_groupby_multi_index
+       206±0.8ms          231±2ms     1.12  timeseries.ToDatetime.time_iso8601_tz_spaceformat
+         199±2ms        221±0.5ms     1.12  packers.Packers.time_packers_read_csv
+         606±3μs          674±5μs     1.11  groupby.GroupBySuite.time_value_counts('float', 100)
+       265±0.9μs          294±3μs     1.11  indexing.MultiIndexing.time_frame_xs_mi_ix
+      8.49±0.1ms         9.39±1ms     1.11  eval.Eval.time_mult('numexpr', 1)
+     8.07±0.04μs      8.91±0.09μs     1.10  timeseries.DatetimeIndex.time_timestamp_tzinfo_cons
+         209±2ms          231±3ms     1.10  groupby.GroupBySuite.time_describe('float', 100)
+          73.8ms           81.4ms     1.10  packers.JSON.time_write_json
+      58.2±0.7μs       64.0±0.7μs     1.10  indexing.IntervalIndexing.time_loc_scalar
+      31.3±0.2μs       34.4±0.6μs     1.10  indexing.Int64Indexing.time_ix_scalar

verifying for correctness and then I'll start digging into them.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor
+      10.3±0.5ms            4.83s   469.35  inference.DtypeInfer.time_timedelta64_2
+     8.94±0.09ms            3.03s   339.45  inference.DtypeInfer.time_datetime64

are real. _maybe_box_datetimelike looks suspicious (this is the RC):

ncalls tottime percall cumtime percall filename:lineno(function)
2000000 6.369 3.185e-06 6.57 3.285e-06 common.py:170(_maybe_box_datetimelike)
2 0.6152 0.3076 7.185 3.593 base.py:813()
2000723/2000456 0.2013 1.006e-07 0.203 1.015e-07 ~:0()

http://pandas.pydata.org/speed/pandas/#inference.DtypeInfer.time_datetime64 points to ~ eef810ef (cc @jreback)

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

DtypeInfer:

+      10.3±0.4ms            4.78s   464.27  inference.DtypeInfer.time_timedelta64_2
+     8.71±0.07ms            2.93s   336.02  inference.DtypeInfer.time_datetime64
+        63.4±2ms            3.84s    60.54  inference.DtypeInfer.time_timedelta64_1

SeriesArthmetic.time_add_offset*

560±20ms       before           after         ratio
     [888c4ec3]       [36c309ed]
+     3.38±0.08ms          298±9ms    87.90  timeseries.SeriesArithmetic.time_add_offset_delta
+     10.00±0.3ms          294±3ms    29.37  timeseries.SeriesArithmetic.time_add_offset_fast
+        560±20ms          803±2ms     1.43  timeseries.SeriesArithmetic.time_add_offset_slow

These are handled by #17980

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

categoricals.Categoricals3.time_rank_string_cat_ordered

5.12±0.08ms       before           after         ratio
     [888c4ec3]       [36c309ed]
+      7.22±0.5ms          139±6ms    19.25  categoricals.Categoricals3.time_rank_string_cat

Seems like this is ranking the objects, instead of codes.

This is handled by #17982

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

packers.*stata.*

46.1±0.01ms       before           after         ratio
     [888c4ec3]       [36c309ed]
+      36.5±0.3ms          601±6ms    16.47  packers.packers_read_stata.time_packers_read_stata
+     46.1±0.01ms            575ms    12.48  packers.packers_read_stata_with_validation.time_packers_read_stata_with_validation
+      30.2±0.7ms            346ms    11.48  packers.STATA.time_write_stata
+          42.5ms            339ms     7.96  packers.STATA.time_write_stata_with_validation

Fixed by #17980

8 remaining items

jbrockmendel

jbrockmendel commented on Oct 25, 2017

@jbrockmendel
Member

For morale purposes: is there any good news?

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

:) Yeah there were quite a few:

-         148±2ms          135±2ms     0.91  gil.nogil_rolling_algos_slow.time_nogil_rolling_median
-     1.77±0.01ms      1.61±0.01ms     0.91  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BQuarterBegin', 1)
-        68.4±1ms       62.1±0.4ms     0.91  hdfstore_bench.HDF5.time_write_store_table_mixed
-     1.51±0.05ms      1.37±0.02ms     0.91  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('Week', 1)
-         359±6ms          325±2ms     0.90  io_bench.read_json_lines.time_read_json_lines
-      11.5±0.3μs      10.4±0.05μs     0.90  period.Algorithms.time_drop_duplicates_pindex
-     3.85±0.04ms      3.48±0.03ms     0.90  stat_ops.stat_ops_level_series_sum_multiple.time_stat_ops_level_series_sum_multiple
-         104±1μs       93.8±0.7μs     0.90  frame_ctor.frame_get_numeric_data.time_frame_get_numeric_data
-     1.73±0.04ms      1.56±0.01ms     0.90  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('QuarterEnd', 2)
-       145±0.9ms          131±1ms     0.90  inference.to_numeric_downcast.time_downcast('string-float', None)
-     1.79±0.02ms      1.61±0.01ms     0.90  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BMonthBegin', 2)
-     4.32±0.04ms      3.89±0.03ms     0.90  timeseries.ToDatetime.time_iso8601_format_no_sep
-     3.27±0.05ms      2.94±0.02ms     0.90  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253_1', 1)
-     3.25±0.07ms      2.91±0.03ms     0.90  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253_1', 2)
-     14.5±0.09ms      12.9±0.06ms     0.89  io_sql.ReadSQLTypes.time_float_read_table_sqlalchemy
-     9.26±0.08ms      8.25±0.02ms     0.89  inference.to_numeric.time_from_str_coerce
-      1.57±0.1ms      1.40±0.02ms     0.89  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BusinessDay', 1)
-     1.82±0.03ms      1.62±0.03ms     0.89  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BMonthBegin', 1)
-          17.2ms           15.2ms     0.89  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253Quarter_1', 2)
-         330±1ms          293±4ms     0.89  replace.replace_convert.time_replace_series_timedelta
-           3.09s            2.74s     0.89  stat_ops.FrameOps.time_op('median', True, 'float', 1)
-      47.4±0.2ms       41.9±0.3ms     0.88  frame_ctor.FromDicts.time_frame_ctor_nested_dict_int64
-      46.8±0.4ms       41.2±0.5ms     0.88  frame_ctor.FromDicts.time_frame_ctor_nested_dict
-     1.18±0.02ms      1.04±0.01ms     0.88  indexing.DataFrameIndexing.time_loc_dups
-         114±4ms        100±0.6ms     0.88  frame_methods.Apply.time_apply_user_func
-     4.40±0.02ms      3.86±0.01ms     0.88  timeseries.ToDatetime.time_iso8601
-         331±3ms          290±4ms     0.88  replace.replace_convert.time_replace_series_timestamp
-     1.76±0.01ms      1.54±0.03ms     0.88  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BYearBegin', 2)
-        255±10μs          224±2μs     0.88  frame_methods.frame_boolean_row_select.time_frame_boolean_row_select
-     1.51±0.04ms      1.32±0.02ms     0.88  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('YearEnd', 2)
-     1.81±0.03ms      1.59±0.03ms     0.88  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BQuarterBegin', 2)
-     1.74±0.02ms      1.52±0.02ms     0.87  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('QuarterEnd', 1)
-        71.1±4μs       62.1±0.6μs     0.87  frame_methods.frame_xs_row.time_frame_xs_row
-     4.40±0.07ms      3.85±0.02ms     0.87  timeseries.ToDatetime.time_iso8601_format
-           6.20s            5.41s     0.87  groupby.GroupBySuite.time_mad('int', 10000)
-     4.40±0.05ms      3.83±0.01ms     0.87  timeseries.ToDatetime.time_iso8601_nosep
-     1.49±0.02ms      1.29±0.03ms     0.87  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('YearEnd', 1)
-        92.5±2μs         80.2±2μs     0.87  period.Properties.time_end_time
-     1.50±0.02ms      1.30±0.02ms     0.86  groupby.groupby_categorical.time_groupby_ordered_sort
-     1.51±0.01ms      1.30±0.02ms     0.86  groupby.groupby_categorical.time_groupby_sort
-     2.00±0.04ms      1.73±0.01ms     0.86  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BusinessHour', 2)
-     1.77±0.05ms      1.52±0.03ms     0.86  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BQuarterEnd', 2)
-         544±5ms          468±2ms     0.86  replace.replace_convert.time_replace_frame_timestamp
-         543±4ms          465±3ms     0.86  replace.replace_convert.time_replace_frame_timedelta
-      7.00±0.1ms      6.00±0.06ms     0.86  timeseries.DatetimeAccessor.time_dt_accessor_normalize
-     2.38±0.03ms      2.03±0.03ms     0.86  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CustomBusinessHour', 1)
-         393±3μs          335±3μs     0.85  join_merge.Append.time_append_homogenous
-     1.82±0.06ms      1.55±0.04ms     0.85  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CDay', 2)
-     2.42±0.04ms      2.06±0.04ms     0.85  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CustomBusinessHour', 2)
-     1.54±0.01ms      1.29±0.02ms     0.84  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('YearBegin', 1)
-     1.87±0.06ms      1.57±0.02ms     0.84  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BQuarterEnd', 1)
-         1.05±0s          873±2ms     0.83  groupby.groupby_frame_apply.time_groupby_frame_df_copy_function
-         421±2ms          347±4ms     0.83  groupby.groupby_frame_apply.time_groupby_frame_apply_df_copy_overhead
-         377±1μs          308±2μs     0.82  algorithms.Algorithms.time_match_strings
-          71.2ms           58.0ms     0.81  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253Quarter_2', 2)
-         581±7μs        472±0.8μs     0.81  frame_methods.Iteration.time_iteritems_cached
-     1.69±0.04ms      1.35±0.01ms     0.80  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('Easter', 2)
-      26.3±0.1ms       21.0±0.5ms     0.80  sparse.sparse_series_to_coo.time_sparse_series_to_coo
-          43.8ms           35.0ms     0.80  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253Quarter_2', 1)
-           11.1s            8.85s     0.79  panel_methods.PanelMethods.time_pct_change_items
-      2.20±0.2ms      1.74±0.04ms     0.79  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('BusinessHour', 1)
-      12.5±0.2μs      9.72±0.09μs     0.78  period.period_standard_indexing.time_get_loc
-         204±2μs        156±0.9μs     0.76  timeseries.Offsets.time_custom_bmonthend_incr
-      13.1±0.3ms       9.91±0.1ms     0.76  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253_2', 1)
-      22.5±0.5ms       16.9±0.2ms     0.75  categoricals.Categoricals2.time_value_counts_dropna
-     2.96±0.02ms      2.21±0.05ms     0.75  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CBMonthBegin', 2)
-        966±10μs          717±7μs     0.74  join_merge.Append.time_append_mixed
-      1.85±0.1ms      1.37±0.01ms     0.74  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('Easter', 1)
-      3.67±0.2ms      2.71±0.02ms     0.74  groupby.GroupBySuite.time_last('float', 10000)
-     4.56±0.07ms      3.37±0.05ms     0.74  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CBMonthEnd', 1)
-      13.7±0.2ms      10.1±0.05ms     0.73  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('FY5253_2', 2)
-         848±9ns         620±10ns     0.73  timestamp.TimestampOps.time_to_pydatetime
-      4.72±0.2ms      3.45±0.08ms     0.73  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CBMonthEnd', 2)
-     2.55±0.07ms           1.86ms     0.73  inference.DtypeInfer.time_float64
-      20.4±0.3ms       14.6±0.3ms     0.72  categoricals.Categoricals2.time_value_counts
-      2.58±0.3ms           1.81ms     0.70  inference.DtypeInfer.time_int64
-      32.7±0.8ms       22.6±0.7ms     0.69  binary_ops.Ops.time_frame_comparison(False, 1)
-         272±6μs          187±6μs     0.69  timeseries.Offsets.time_custom_bmonthbegin_incr_n
-      16.1±0.1ms      11.0±0.05ms     0.68  groupby.groupby_categorical.time_groupby_ordered_nosort
-         256±6μs          174±2μs     0.68  timeseries.Offsets.time_custom_bmonthend_incr_n
-      57.7±0.6ms       38.5±0.7ms     0.67  join_merge.Concat.time_concat_small_frames
-     3.95±0.05ms      2.63±0.09ms     0.67  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('CBMonthBegin', 1)
-     1.35±0.04ms         891±20μs     0.66  replace.replace_replacena.time_replace_replacena
-        32.5±2ms         21.4±1ms     0.66  binary_ops.Ops.time_frame_comparison(False, 'default')
-      10.7±0.1ms       6.98±0.1ms     0.65  groupby.groupby_categorical.time_groupby_nosort
-      3.68±0.2ms      2.39±0.03ms     0.65  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('WeekOfMonth', 2)
-           8.77s            5.47s     0.62  panel_methods.PanelMethods.time_pct_change_minor
-         297±2μs          181±2μs     0.61  timeseries.Offsets.time_custom_bmonthend_decr_n
-           9.15s            5.54s     0.61  panel_methods.PanelMethods.time_pct_change_major
-     8.82±0.06ms      5.31±0.05ms     0.60  groupby.groupby_categorical.time_groupby_extra_cat_nosort
-      4.04±0.3ms      2.42±0.06ms     0.60  frame_ctor.FrameConstructorDTIndexFromOffsets.time_frame_ctor('WeekOfMonth', 1)
-     1.84±0.01μs      1.09±0.02μs     0.59  period.Properties.time_is_leap_year
-        67.0±1ms       39.4±0.1ms     0.59  eval.Eval.time_chained_cmp('python', 'all')
-      28.5±0.6ms       16.6±0.5ms     0.58  frame_methods.frame_fancy_lookup.time_frame_fancy_lookup_all
-      26.1±0.2μs       14.7±0.2μs     0.56  timeseries.Offsets.time_timeseries_year_incr
-           8.89y            5.00y     0.56  io_bench.read_json_lines.peakmem_read_json_lines
-         266±3μs          147±3μs     0.55  timeseries.Offsets.time_custom_bmonthbegin_decr_n
-     1.82±0.02μs      1.00±0.01μs     0.55  period.Properties.time_daysinmonth
-     1.82±0.03μs          977±8ns     0.54  period.Properties.time_year
-     1.80±0.03μs         959±10ns     0.53  period.Properties.time_second
-     1.80±0.01μs         950±10ns     0.53  period.Properties.time_dayofweek
-     1.83±0.01μs         956±10ns     0.52  period.Properties.time_dayofyear
-     1.82±0.02μs         948±30ns     0.52  period.PeriodProperties.time_hour
-     1.79±0.01μs          931±3ns     0.52  period.Properties.time_month
-     1.82±0.01μs          942±7ns     0.52  period.PeriodProperties.time_second
-     1.81±0.03μs         925±20ns     0.51  period.Properties.time_quarter
-     1.83±0.02μs         933±10ns     0.51  period.PeriodProperties.time_day
-     1.85±0.01μs         943±20ns     0.51  period.PeriodProperties.time_quarter
-     1.81±0.02μs         919±10ns     0.51  period.Properties.time_minute
-     1.90±0.03μs         965±10ns     0.51  period.PeriodProperties.time_year
-     1.85±0.02μs         936±20ns     0.51  period.PeriodProperties.time_month
-      22.6±0.3μs      11.4±0.07μs     0.50  timeseries.Offsets.time_timeseries_year_apply
-     1.85±0.03μs          929±5ns     0.50  period.Properties.time_day
-     2.00±0.05μs         999±10ns     0.50  period.Properties.time_week
-     1.90±0.02μs         939±10ns     0.49  period.Properties.time_qyear
-     1.90±0.02μs         930±10ns     0.49  period.PeriodProperties.time_minute
-     1.96±0.03μs         912±10ns     0.47  period.Properties.time_hour
-     15.2±0.07ms      6.96±0.05ms     0.46  binary_ops.Ops.time_frame_comparison(True, 'default')
-       321±0.8ms          143±1ms     0.44  sparse.sparse_series_to_frame.time_sparse_series_to_frame
-      49.4±0.4ms       21.3±0.2ms     0.43  eval.Eval.time_chained_cmp('python', 1)
-     8.61±0.01ms      3.68±0.04ms     0.43  categoricals.Categoricals.time_union
-     11.1±0.05ms      2.74±0.06ms     0.25  binary_ops.Ops.time_frame_comparison(True, 1)
-        79.5±1ms       14.8±0.2ms     0.19  categoricals.Categoricals2.time_set_categories
-        3.45±0ms          439±3μs     0.13  timeseries.DatetimeIndex.time_timeseries_is_month_start
-           2.47s          231±2ms     0.09  sparse.sparse_frame_constructor.time_sparse_from_scipy
-     7.11±0.03μs          482±6ns     0.07  timestamp.TimestampProperties.time_weekday_name
-           2.46s          106±1ms     0.04  sparse.sparse_frame_constructor.time_sparse_from_dict
-        915±20μs       23.5±0.7μs     0.03  timeseries.DatetimeAccessor.time_dt_accessor
-       105±0.4ms      2.38±0.04ms     0.02  rolling.SeriesRolling.time_rolling_quantile_0
-         116±1ms      2.36±0.01ms     0.02  rolling.SeriesRolling.time_rolling_quantile_1
-       101±0.6ms      1.98±0.03ms     0.02  rolling.DataframeRolling.time_rolling_quantile_0
-      31.6±0.4μs          611±2ns     0.02  timestamp.TimestampOps.time_to_pydatetime_tz
-         123±2ms      1.99±0.03ms     0.02  rolling.DataframeRolling.time_rolling_quantile_1
-     10.1±0.09μs          147±1ns     0.01  timestamp.TimestampProperties.time_microsecond
-         197±1ms      2.55±0.03ms     0.01  rolling.SeriesRolling.time_rolling_quantile_0_l
-         201±1ms      2.13±0.04ms     0.01  rolling.DataframeRolling.time_rolling_quantile_0_l
-         260±1ms      2.49±0.04ms     0.01  rolling.SeriesRolling.time_rolling_quantile_1_l
-         263±2ms      2.17±0.02ms     0.01  rolling.DataframeRolling.time_rolling_quantile_1_l
-     3.51±0.02ms      4.59±0.04μs     0.00  hdfstore_bench.HDF5.time_store_repr
-     3.46±0.03ms      4.38±0.07μs     0.00  hdfstore_bench.HDF5.time_store_str
-      15.9±0.2ms      1.37±0.01μs     0.00  index_object.Range.time_min
-      16.1±0.3ms      1.35±0.01μs     0.00  index_object.Range.time_max
-      15.8±0.1ms      1.26±0.02μs     0.00  index_object.Range.time_max_trivial
-      16.0±0.1ms      1.23±0.02μs     0.00  index_object.Range.time_min_trivial
jbrockmendel

jbrockmendel commented on Oct 25, 2017

@jbrockmendel
Member

-b timeseries.DatetimeIndex.time_infer_

These may be improved by #17830 and/or #17746.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

For period.Algorithms.time_drop_duplicates_pseries, it seems like Period.freqstr is being called somewhere inside _ensure_data / ensure_object. Could that be avoided?

jbrockmendel

jbrockmendel commented on Oct 25, 2017

@jbrockmendel
Member

Are you sure its freqstr in particular? It seems like drop_duplicates would make a bunch of calls to Period.__eq__, which then calls self.freq.__eq__(other.freq) which is very slow.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

I think it's in Period.__hash__, but confirming now.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

Hmm that may be it:

diff --git a/pandas/_libs/period.pyx b/pandas/_libs/period.pyx
index cf6ef91d3..f28ee2aac 100644
--- a/pandas/_libs/period.pyx
+++ b/pandas/_libs/period.pyx
@@ -718,7 +718,7 @@ cdef class _Period(object):
                             (type(self).__name__, type(other).__name__))

     def __hash__(self):
-        return hash((self.ordinal, self.freqstr))
+        return hash((self.ordinal, self.freq))

     def _add_delta(self, other):
         if isinstance(other, (timedelta, np.timedelta64, offsets.Tick)):
(

master:

In [1]: import pandas as pd

In [2]: p = pd.Period("2010", freq="M")

In [3]: %timeit hash(p)
807 ns ± 8.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

with that diff:


In [1]: import pandas as pd

In [2]: p = pd.Period("2010", freq="M")

In [3]: %timeit hash(p)
4.84 µs ± 42.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Let's see if that breaks anything.

jbrockmendel

jbrockmendel commented on Oct 25, 2017

@jbrockmendel
Member

Can you try that with a handful of different frequencies? I'd be shocked if hash(freq) is faster than hash(freq.freqstr)

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

FWIW, it doesn't seem promising w.r.t. the benchmark (see the 2nd and 4th) lines. I rebuilt the c extensions between these two. My branch with the new hash is on top, master is on bottom.

 ◰³ pandas-dev  ~/E/p/l/p/s/pandas   period-freq-hash  asv_bench  asv dev -b 'period.Algorithms.time_[drop|value]'    4584ms  Wed Oct 25 14:12:40 2017
· Discovering benchmarks
· Running 4 total benchmarks (1 commits * 1 environments * 4 benchmarks)
[  0.00%] ·· Building for existing-py_Users_taugspurger_Envs_pandas-dev_bin_python3.6
[  0.00%] ·· Benchmarking existing-py_Users_taugspurger_Envs_pandas-dev_bin_python3.6
[ 25.00%] ··· Running period.Algorithms.time_drop_duplicates_pindex                                                                                   49.0μs
[ 50.00%] ··· Running period.Algorithms.time_drop_duplicates_pseries                                                                                  18.5ms
[ 75.00%] ··· Running period.Algorithms.time_value_counts_pindex                                                                                       402μs
[100.00%] ··· Running period.Algorithms.time_value_counts_pseries                                                                                     22.8ms
 ◰³ pandas-dev  ~/E/p/l/p/s/pandas   period-freq-hash  asv_bench  asv dev -b 'period.Algorithms.time_[drop|value]'        6s  Wed Oct 25 14:13:37 2017
· Discovering benchmarks
· Running 4 total benchmarks (1 commits * 1 environments * 4 benchmarks)
[  0.00%] ·· Building for existing-py_Users_taugspurger_Envs_pandas-dev_bin_python3.6
[  0.00%] ·· Benchmarking existing-py_Users_taugspurger_Envs_pandas-dev_bin_python3.6
[ 25.00%] ··· Running period.Algorithms.time_drop_duplicates_pindex                                                                                   48.0μs
[ 50.00%] ··· Running period.Algorithms.time_drop_duplicates_pseries                                                                                  3.14ms
[ 75.00%] ··· Running period.Algorithms.time_value_counts_pindex                                                                                       405μs
[100.00%] ··· Running period.Algorithms.time_value_counts_pseries                                                                                     3.43ms

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

@jreback if you have time to look at the indexing ones, I'd appreciate it: #17861 (comment) and #17861 (comment)

I'm not sure there's a whole lot to be done though. The first is because we have to check for missing values with list-like indexers now, to raise the warning.

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

Oh, I'm dumb. Mixed up nanoseconds and microseconds in #17861 (comment)

TomAugspurger

TomAugspurger commented on Oct 25, 2017

@TomAugspurger
ContributorAuthor

I think we decided in #17574 that the sparse changes were OK?

jorisvandenbossche

jorisvandenbossche commented on Oct 25, 2017

@jorisvandenbossche
Member

@jreback if you have time to look at the indexing ones, I'd appreciate it: #17861 (comment) and #17861 (comment)

The series getitem ones (s[np.arange(10000)]) are due to changing reindex to loc, and apparently loc is slower.

TomAugspurger

TomAugspurger commented on Oct 27, 2017

@TomAugspurger
ContributorAuthor

I think everything has been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    PerformanceMemory or execution speed performance

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jreback@jorisvandenbossche@TomAugspurger@jbrockmendel

        Issue actions

          PERF: Regressions since 0.20.3 · Issue #17861 · pandas-dev/pandas