Python is a very dynamic language and not easy to optimize. Ryan Kelly has a solution for this, he is the creator of library called Promise. Promise allows you to declare your functions are: invariant, constant, pure, and sensible. This removes many of the dynamic features of Python to improve performance using runtime byte-code optimizations. Using similar restrictions we can optimize the output of the PythonScript compiler to gain much higher performance.
To speed up attribute access we can use a new class decorator @inline, this tells the PythonScript compiler to bypass get_attribute and directly return the attribute from the instances __dict__. The compiler is smart enough to know that if the attribute is not found on the instance, and the class has defined a custom __getattr__ method, to directly inline and call __getattr__. The compiler knows which attributes are to be found on the instance by introspecting its methods, and checking for each time an attribute is assigned to self.
In order for the PythonScript compiler to perform these inline optimizations, it needs to know which class an instance is. When a class instance is created, it knows that variable name is the given class, however if the instance is passed to a function that returns it and assigns it to a new variable, the compiler will no longer know what type it is. The workaround to manually define the type of an instance is using assert isinstance( a, SomeClass ). Another way to declare the type of a variable is using PythonScript's special var() function and using keyword arguments like this: var(x=SomeType), this feature was added in this commit.
@inline class A: pass a = A() b = a ## for this simple case, the compiler still knows that "b" is an instance of A def opaque(x): return x c = opaque( b ) ## the compiler is not sure what "c" is assert isinstance(c, A) ## this informs the compiler that "c" is an instance of A ... ## any following code using "c" will have inline optimizations.
In my fork of PythonScript I have changed it to be compatible with the Closure compiler. Using its "Advanced Optimizations" option, it is able to inline the body of simple functions, this provides another level of in-lining that can speed up the code even more. Closure is able to compress and optimize the code in other ways as well.
TestThe test code below compiled with PythonScript+Closure and run in Google Chrome, is faster than PyPy by two times, and 32X faster than normal Python.
def somefunc(): return 1 @inline class A: def __init__(self): self.x = 1 self.y = 2 self.z = 3 #def __getattr__(self,name): def __getattr__(): ## a method that takes no arguments tells PythonScript ## to optimize the call for no arguments return random() a = A() now = time() r = 0.0 i = 0 while i < 1000000: r += a.some_dynamic_attribute i += somefunc() print( time()-now )