def test_arg_type_type_list_guard(self): def func(a, b, c): return 'slow' def func2(a, b, c): return 'fast' fat.specialize(func, func2, [fat.GuardArgType(2, [list, set])]) guard = fat.GuardArgType(2, (list, set)) self.check_specialized(func, (func2.__code__, [guard])) # If the guard fails, the specialized function must no be removed self.assertEqual(func(0, 1, "abc"), 'slow') self.check_specialized(func, (func2.__code__, [guard]))
def test_arg_type(self): def func(x): return "slow: %s" % x def fast(x): return "fast: %s" % x self.assertNotSpecialized(func) self.assertNotSpecialized(fast) fat.specialize(func, fast, [fat.GuardArgType(0, (int, ))]) self.assertEqual(func(3), 'fast: 3') # FIXME: implement keywords #self.assertEqual(func(x=4), 'fast: 4') # calling with the wrong number of parameter must not disable the # optimization with self.assertRaises(TypeError): func() with self.assertRaises(TypeError): func( 1, 2, ) self.assertEqual(func(5), 'fast: 5') # wrong type, skip optimization self.assertEqual(func(6.0), 'slow: 6.0') # optimization must not be disabled after call with wrong types self.assertEqual(func(7), 'fast: 7')
def test_guard_arg_type(self): guard = fat.GuardArgType(2, (int, )) self.assertEqual(guard.arg_index, 2) self.assertEqual(guard.arg_types, (int, )) self.assertEqual(guard(1, 2, 3), 0) self.assertEqual(guard(1, 2, "hello"), 1) # FIXME: keywords are not supported yet self.assertEqual(guard(1, 2, arg=3), 1)
def test_add_arg_type_guard_error(self): # missing 'arg_index' and/or 'type' keys with self.assertRaises(TypeError): fat.GuardArgType() with self.assertRaises(TypeError): fat.GuardArgType(0) with self.assertRaises(TypeError) as cm: fat.GuardArgType("abc", (str, )) with self.assertRaises(TypeError) as cm: # arg_type argument is not a type fat.GuardArgType(2, 123) self.assertEqual(str(cm.exception), "arg_types must be a type or an iterable") with self.assertRaises(TypeError) as cm: # arg_type items are not types fat.GuardArgType(2, (123, )) self.assertEqual(str(cm.exception), "arg_type must be a type, got int")
def test_arg_type_int(self): def func(obj): return 'slow' def fast(obj): return 'fast' self.assertNotSpecialized(func) self.assertNotSpecialized(fast) fat.specialize(func, fast, [fat.GuardArgType(0, (int, ))]) self.assertEqual(func(5), 'fast') self.assertEqual(func("abc"), 'slow')
def main(): if fat.get_specialized(func) or fat.get_specialized(func2): print("ERROR: functions already specialized!") sys.exit(1) fat.specialize(func2, fast_func2, [fat.GuardArgType(0, (list, ))]) for range_pow10 in (0, 1, 3, 5): print("range(10 ** %s)" % range_pow10) dt = bench_list('func', range_pow10) print("- original bytecode: %s" % format_dt(dt)) dt2 = bench_list('func2', range_pow10) print("- append=obj.append with guards: %s" % compared_dt(dt2, dt)) dt2 = bench_list('fast_func2', range_pow10) print("- append=obj.append: %s" % compared_dt(dt2, dt))
def test_arg_type_class(self): class MyClass: pass def func(obj): return 'slow' def fast(obj): return 'fast' self.assertNotSpecialized(func) self.assertNotSpecialized(fast) fat.specialize(func, fast, [fat.GuardArgType(0, (MyClass, ))]) obj = MyClass() self.assertEqual(func(obj), 'fast') self.assertEqual(func("test"), 'slow')