Ralph Hauwert put a very interesting blog post up no his blog about Adobe Alchemy. Basically he was reading my mind with this post.
I want to a step further now. But please keep in mind that I am definitly not a compiler expert or have deep knowledge of the Flash Player. Everything I write about is in my opinion common sense and comes from a long time of reverse engineering and autodidactic learning.
Continue reading ‘Alchemy, ActionScript and the ASC’
Ralph Hauwert put a very interesting blog post up no his blog about Adobe Alchemy. Basically he was reading my mind with this post.
I want to a step further now. But please keep in mind that I am definitly not a compiler expert or have deep knowledge of the Flash Player. Everything I write about is in my opinion common sense and comes from a long time of reverse engineering and autodidactic learning.
Alchemy
First of all I have to say that Alchemy is a great research project and I have full respect for Scott Peterson and his work. He did an awesome job and I am more than happy that Alchemy has now been released on labs because people begin to question now the Flash Player, ActionScript and the ASC (ActionScript Compiler).
So why is Alchemy faster than using plain ActionScript -- or is that true at all? I do not want to disappoint anyone here but writing C/C++ code instead of ActionScript is not the right way. Alchemy will never be faster than your plain handoptimized ActionScript and it still has to prove for me that it is actually faster. All my comparisons between Alchemy and ActionScript showed that using ActionScript is in most cases faster.
But it makes sense to use Alchemy. An audio encoder for instance runs for a long time on its own without having to exchange data. Currently it is very slow to transfer data between Alchemy and ActionScript on every frame. This does not mean Alchemy is bad, but it will not work for your fast inverse square root algorithm.
So why can Alchemy be faster at all? There are a couple of reasons for that.
C/C++ can be compiled and optimized much better than ActionScript
The language offers you features you would dream about as an ActionScript programmer (operator overloading, method inlining, templates, etc.)
The LLVM does a really good job on optimizing its intermediate language
Alchemy comes with some new opcodes for the Flash Player that allow very fast ByteArray operations
Alchemy uses a modified ASC that supports inlining of Flash Player bytecodes.
So just to make one thing cristal clear: If the new opcodes would not exist, Alchemy would produce very poor results in terms of execution speed. But albeit that I have to disappoint you about the execution speed of Alchemy in general. Nicolas Cannasse wrote an interesting blog post about this issue and I completely agree. ActionScript does not support a lot of features which C/C++ offers -- pointers for instance. All those features have to be wrapped and this means a significant speed loss.
But I do not want to start an Alchemy bashing here. I still think it is a really great technology and the main use case is not fast code execution. But it brings me to my next points: The ActionScript language and the ASC.
ActionScript
ActionScript has been designed several years ago and Adobe had always the incentive to be ECMA compilant. Being standards compilant reduces a certain level of innovation and recuded the power of the Flash Player in the last years. Right now, ActionScript 3 is not an ECMA compilant language. And I am not saying this because ECMA Script 4 has been dropped. ActionScript 3 added additional "features" even before that happened.
For a long time ActionScript 3 has been very close in terms of its ECMA compilance but I think it is now time for innovation. The ActionScript 3 language does not fulfill most of the professional needs.
Have you ever looked at haXe? I hope you did. haXe is definitly not perfect but I want give you a small excerpt of haXe language features which will make your mouth water:
You are able to use type parameters
You are able to use function types like Event -> Void for an event listener instead of Function
Enums instead of the public static const convulsion
Why am I talking about haXe at all? Java has most of those features implemented as well and several other languages too. But haXe can output a SWF so we can compare it to ActionScript. haXe is in a lot of ways superior to ActionScript and I did not talk about the compiler yet.
The quintessence is that ActionScript is not a feature rich language compared to mature ones. And even a single French genius can develop something better than a multi-million dollar company. What the hell is going on here?
The main problem of ActionScript is that you lose most of your types along the way and therefore the compiler can not produce a good output. E.g. everytime you put some object into an Array in ActionScript its type is lost unless you cast of course when reading again -- and I hope you do that. This is a really big problem. This is the reason why Alchemy can produce "better ActionScript" than you. Not because you are stupid but because you do not have the tools in ActionScript to do that. And this is a shame for Adobe. So many great developers could produce such a great output but they are not allowed to.
ActionScript Compiler
One of the main problem in the whole Flash universe is the ActionScript compiler. This is a little bit harder to explain because it is a little bit more abstract. Some problems exist because of the ActionScript language nature. But some problems exist because of the compiler itself. Let me explain this with an example:
package {
public final class Example extends flash.display.Sprite {
public function Example() {
var a: int = 1+2;
var b: int = a;
var c: int = b+1;
}
}
}
This code will produce exactly this output for the constructor:
get_local0
pushscope
get_local0
constructsuper 0
pushbyte 1
pushbyte 2
add
convert_i
set_local1
get_local1
convert_i
set_local2
get_local2
pushbyte 1
add
convert_i
set_local3
returnvoid
The interesting part has been marked bold. Let me explain what is going on here:
Put value 1 on the stack
Put value 2 on the stack
Add the two values which are on the stack together using floating point calculus
Convert this floating point value to an integer
Set this value to local register one which is a
Put the value of local register one on the stack
Convert this floating point value to an integer
Set the value to local register two which is b
Put the value of local register two on the stack
Put value 1 on the stack
Add the two values which are on the stack together using floating point calculus
Convert this floating point value to an integer
Set this value to local register three which is c
Basically this is an example for the worst output a compiler could produce. First of all b is not needed at all in our code. We hold just the value a in b. a holds a constant value 3. Why do we have to add this stuff together at runtime everytime if it is constant? For c we add the constant value 1 to the constant value 3 which has been stored in a. The compiler should know at this point three things: a is constant, b is not needed, c is constant. The compiler could just set c to the integer value of 4. This is also what I would expect for a SmallWebFormat.
But to make it even more interesting: c is not used at all. So why does the constructor contain any bytecode at all besides calling the super constructor? And to make it a little bit more absurd: Try doing the same in PixelBender and use Tinic's disassembler. You will see that you will not find any of your local variables in the PixelBender bytecode -- which is correct. And the answer why the PixelBender compiler is smarter than the ASC is quite easy: Adobe uses the LLVM for PixelBender as well. Remember the LLVM is what Alchemy is using. This means basically that PixelBender has a better compiler than we have for ActionScript. This is sad and insane but true.
With the haXe compiler you will get nearly the same output as the ASC with certain differences. All the variables are integer values and therefore haXe uses integer calculus. And the last addition does not involve b at all. haXe will not ignore that a, b and c are not used at all. But as I said: haXe is definitly not perfect -- but it is by far better.
I have asked for certain features a lot in the past and implemented them for myself. I asked Adobe to support the __asm keyword even before Alchemy and they refused it. Of course I am a little bit disappointed about that because now they use it for Alchemy and they see it makes sense. Basically having a __asm keyword allows you to get around the nonsense which the ASC produces at least for performance critical loops. This is why I started writing AS3C but it is basically a stupid idea to try optimizing on a byte code level but it integrated very well into my daily workflow.
The Flash Player could work much faster if we could access certain things with ActionScript. The lookup of a class can be stored in a local variable for instance which gives a significat speed boost. haXe already allows you to do that via var m = Math. Why do we have to wait for such things so long?
Thoughts
Now after writing about Alchemy, ActionScript and the ASC I think that you get the idea. What we need is a compiler that works. And once the new Alchemy opcodes are supported in the ASC it will be much more fun to write your lightning fast ActionScript code instead of converting C libraries. We need a mature language which allows us to work in professional large-scale environments and which allows the compiler to produce a good output.
Libraries which are a community-darling could become even better, easier to use and faster in execution speed which would result in better user experiences.
I would like to see a faster and more innovative development of ActionScript and the ASC. But then there are the politics and all the bussiness stuff so we will have to wait probably for ages until we get what we need. Right now we can use alternatives such as haXe. And the good thing is that other companies do not sleep as well. I would love to write C# instead of ActionScript but Silverlight just sucks. Maybe someone could write a C#->LLVM->ActionScript->SWF compiler toolkit?