Repository: numba/numba

Issue:
Significant performance regression on master
We have detected a significant performance regression on master that hints at a potential bug. This was initially discovered on a RaspberryPi because the tests in question did not finish within the given timeout.

In order to reproduce, the following command line invocation should suffice:

```
python -m numba.runtests -m 1 numba.tests.test_unicode_array.TestUnicodeArray -v
```

When comparing the released `0.53.1` to the current `master` (b29e3072f6dea51a617e48847eb53b34d9a1182f), the following performance characteristics arise ( a patch was used to measure the test time) on a OSX Macbook:

```
# test_name,   0.53.1,   master

test_contains_getitem2        ,5.127951145172119   ,23.24689292907715
test_equal_getitem            ,2.191329002380371   ,9.887646913528442
test_equal_getitem_value      ,0.858428955078125   ,6.956943035125732
test_getitem                  ,0.3324911594390869  ,0.2827298641204834
test_getitem2                 ,0.48192572593688965 ,1.5861670970916748
test_getitem_key              ,2.863844871520996   ,17.289783000946045
test_greaterequal_getitem     ,1.0460143089294434  ,3.3156650066375732
test_greaterthan_getitem      ,0.6435327529907227  ,2.9670751094818115
test_hash                     ,1.9335548877716064  ,19.6356999874115
test_join                     ,1.5721981525421143  ,7.845102071762085
test_lessequal_getitem        ,0.6597537994384766  ,4.928839206695557
test_lessthan_getitem         ,0.4733729362487793  ,3.9484970569610596
test_notequal_getitem         ,1.001673936843872   ,15.503906011581421
test_notequal_getitem_value   ,0.7803142070770264  ,10.68653392791748
test_return_add               ,4.560302734375      ,39.159672021865845
test_return_bool              ,0.3563261032104492  ,1.7835299968719482
test_return_bytes             ,0.10456395149230957 ,0.13011693954467773
test_return_center1           ,6.370193958282471   ,85.61256217956543
test_return_center2           ,9.89309811592102    ,102.96373724937439
test_return_endswith          ,5.765472888946533   ,148.66338920593262
test_return_find              ,1.623425006866455   ,99.3564178943634
test_return_iadd              ,2.8009860515594482  ,48.19328570365906
test_return_isascii           ,0.21001815795898438 ,2.7776288986206055
test_return_isupper           ,1.0657482147216797  ,21.325128078460693
test_return_join              ,4.783251047134399   ,70.04828786849976
test_return_len               ,0.2606079578399658  ,3.0345370769500732
test_return_ljust1            ,4.972663164138794   ,149.1891930103302
test_return_ljust2            ,8.890583992004395   ,169.83914709091187
test_return_lstrip1           ,2.66038179397583    ,166.99533319473267
test_return_lstrip2           ,5.679470062255859   ,223.41141605377197
test_return_mul               ,2.9575841426849365  ,81.77414178848267
test_return_not               ,0.35460615158081055 ,5.105407953262329
test_return_rfind             ,1.944978952407837   ,169.01077604293823
test_return_rjust1            ,5.109899044036865   ,223.7612030506134
test_return_rjust2            ,8.761782884597778   ,242.34173798561096
test_return_rstrip1           ,2.642690658569336   ,239.3104088306427
test_return_rstrip2           ,5.547667026519775   ,312.7847640514374
test_return_split1            ,3.2903900146484375  ,222.60474586486816
test_return_split2            ,9.758163928985596   ,940.7669258117676
test_return_split3            ,7.695507049560547   ,1038.3315179347992
test_return_startswith        ,1.264441967010498   ,161.2569239139557
test_return_str               ,0.17267704010009766 ,18.922950744628906
test_return_strip1            ,2.894136905670166   ,495.935085773468
test_return_strip2            ,5.488708019256592   ,648.6054871082306
test_return_upper             ,1.9625248908996582  ,126.70889592170715
test_return_zfill             ,4.687292814254761   ,218.33027410507202
test_setitem                  ,0.1820211410522461  ,0.24275612831115723
test_setitem2                 ,0.4017829895019531  ,0.5613293647766113
test_setitem_literal          ,0.11194014549255371 ,0.16814112663269043
```

As can be seen the runtime for some tests increases by several orders of magnitude.

Also, these tests are listed in alphabetical order. This is not the order they were executed in. We also observe (anecdotally). that test times increase as more tests are executed which indicates some kind of compounding.

During a `git bisect` the following commit was identified to be the culprit:  d2d4e8ad
Significant performance regression on master
We have detected a significant performance regression on master that hints at a potential bug. This was initially discovered on a RaspberryPi because the tests in question did not finish within the given timeout.

In order to reproduce, the following command line invocation should suffice:

```
python -m numba.runtests -m 1 numba.tests.test_unicode_array.TestUnicodeArray -v
```

When comparing the released `0.53.1` to the current `master` (b29e3072f6dea51a617e48847eb53b34d9a1182f), the following performance characteristics arise ( a patch was used to measure the test time) on a OSX Macbook:

```
# test_name,   0.53.1,   master

test_contains_getitem2        ,5.127951145172119   ,23.24689292907715
test_equal_getitem            ,2.191329002380371   ,9.887646913528442
test_equal_getitem_value      ,0.858428955078125   ,6.956943035125732
test_getitem                  ,0.3324911594390869  ,0.2827298641204834
test_getitem2                 ,0.48192572593688965 ,1.5861670970916748
test_getitem_key              ,2.863844871520996   ,17.289783000946045
test_greaterequal_getitem     ,1.0460143089294434  ,3.3156650066375732
test_greaterthan_getitem      ,0.6435327529907227  ,2.9670751094818115
test_hash                     ,1.9335548877716064  ,19.6356999874115
test_join                     ,1.5721981525421143  ,7.845102071762085
test_lessequal_getitem        ,0.6597537994384766  ,4.928839206695557
test_lessthan_getitem         ,0.4733729362487793  ,3.9484970569610596
test_notequal_getitem         ,1.001673936843872   ,15.503906011581421
test_notequal_getitem_value   ,0.7803142070770264  ,10.68653392791748
test_return_add               ,4.560302734375      ,39.159672021865845
test_return_bool              ,0.3563261032104492  ,1.7835299968719482
test_return_bytes             ,0.10456395149230957 ,0.13011693954467773
test_return_center1           ,6.370193958282471   ,85.61256217956543
test_return_center2           ,9.89309811592102    ,102.96373724937439
test_return_endswith          ,5.765472888946533   ,148.66338920593262
test_return_find              ,1.623425006866455   ,99.3564178943634
test_return_iadd              ,2.8009860515594482  ,48.19328570365906
test_return_isascii           ,0.21001815795898438 ,2.7776288986206055
test_return_isupper           ,1.0657482147216797  ,21.325128078460693
test_return_join              ,4.783251047134399   ,70.04828786849976
test_return_len               ,0.2606079578399658  ,3.0345370769500732
test_return_ljust1            ,4.972663164138794   ,149.1891930103302
test_return_ljust2            ,8.890583992004395   ,169.83914709091187
test_return_lstrip1           ,2.66038179397583    ,166.99533319473267
test_return_lstrip2           ,5.679470062255859   ,223.41141605377197
test_return_mul               ,2.9575841426849365  ,81.77414178848267
test_return_not               ,0.35460615158081055 ,5.105407953262329
test_return_rfind             ,1.944978952407837   ,169.01077604293823
test_return_rjust1            ,5.109899044036865   ,223.7612030506134
test_return_rjust2            ,8.761782884597778   ,242.34173798561096
test_return_rstrip1           ,2.642690658569336   ,239.3104088306427
test_return_rstrip2           ,5.547667026519775   ,312.7847640514374
test_return_split1            ,3.2903900146484375  ,222.60474586486816
test_return_split2            ,9.758163928985596   ,940.7669258117676
test_return_split3            ,7.695507049560547   ,1038.3315179347992
test_return_startswith        ,1.264441967010498   ,161.2569239139557
test_return_str               ,0.17267704010009766 ,18.922950744628906
test_return_strip1            ,2.894136905670166   ,495.935085773468
test_return_strip2            ,5.488708019256592   ,648.6054871082306
test_return_upper             ,1.9625248908996582  ,126.70889592170715
test_return_zfill             ,4.687292814254761   ,218.33027410507202
test_setitem                  ,0.1820211410522461  ,0.24275612831115723
test_setitem2                 ,0.4017829895019531  ,0.5613293647766113
test_setitem_literal          ,0.11194014549255371 ,0.16814112663269043
```

As can be seen the runtime for some tests increases by several orders of magnitude.

Also, these tests are listed in alphabetical order. This is not the order they were executed in. We also observe (anecdotally). that test times increase as more tests are executed which indicates some kind of compounding.

During a `git bisect` the following commit was identified to be the culprit:  d2d4e8ad


Discussion:

Resolving patch:
diff --git a/numba/core/cpu_options.py b/numba/core/cpu_options.py
--- a/numba/core/cpu_options.py
+++ b/numba/core/cpu_options.py
@@ -44,11 +44,18 @@ def __bool__(self):
     def __repr__(self):
         return f"FastMathOptions({self.flags})"
 
+    def __eq__(self, other):
+        if type(other) is type(self):
+            return self.flags == other.flags
+        return NotImplemented
+
 
 class ParallelOptions(object):
     """
     Options for controlling auto parallelization.
     """
+    __slots__ = ("enabled", "comprehension", "reduction", "inplace_binop",
+                 "setitem", "numpy", "stencil", "fusion", "prange")
 
     def __init__(self, value):
         if isinstance(value, bool):
@@ -88,6 +95,16 @@ def __init__(self, value):
             msg = "Expect parallel option to be either a bool or a dict"
             raise ValueError(msg)
 
+    def _get_values(self):
+        """Get values as dictionary.
+        """
+        return {k: getattr(self, k) for k in self.__slots__}
+
+    def __eq__(self, other):
+        if type(other) is type(self):
+            return self._get_values() == other._get_values()
+        return NotImplemented
+
 
 class InlineOptions(object):
     """
@@ -137,3 +154,8 @@ def value(self):
         The raw value
         """
         return self._inline
+
+    def __eq__(self, other):
+        if type(other) is type(self):
+            return self.value == other.value
+        return NotImplemented
diff --git a/numba/core/targetconfig.py b/numba/core/targetconfig.py
--- a/numba/core/targetconfig.py
+++ b/numba/core/targetconfig.py
@@ -147,13 +147,6 @@ def __eq__(self, other):
         else:
             return NotImplemented
 
-    def __ne__(self, other):
-        eq = self.__eq__(other)
-        if eq is NotImplemented:
-            return NotImplemented
-        else:
-            return eq
-
     def values(self):
         """Returns a dict of all the values
         """
diff --git a/numba/stencils/stencilparfor.py b/numba/stencils/stencilparfor.py
--- a/numba/stencils/stencilparfor.py
+++ b/numba/stencils/stencilparfor.py
@@ -666,7 +666,8 @@ def get_stencil_ir(sf, typingctx, args, scope, loc, input_dict, typemap,
         raise ValueError("Cannot use the reserved word 'out' in stencil kernels.")
 
     # get typed IR with a dummy pipeline (similar to test_parfors.py)
-    targetctx = CPUContext(typingctx)
+    from numba.core.registry import cpu_target
+    targetctx = cpu_target.target_context
     with cpu_target.nested_context(typingctx, targetctx):
         tp = DummyPipeline(typingctx, targetctx, args, stencil_func_ir)
 


Test patch: