Adobe 自从2007年中推出了AS3支持了面向对象的开发方 式之后, 可谓动作不断. 去年又将AVM2的核心虚拟机tamarin 捐赠给了ECMA4 , 又将FlexBuild2直接升级到FlexBuild3, 这不,在08年末,又蹦出一个 Adobe Alchemy, 这在战略上具有极为重要意义. 而FLASH 从一个简单的动画客户端,一跃升级成一个未来富媒体应用程序的平台. 从这一系列战略步骤,不难看出ADOBE想成为WEB乃至桌面开发霸主的野心! 微软你要小心了.
那么你可能要问了, 为什么Alchemy这么重要呢? 作为FLASH实践者, 效率问题是众所周知的. 因为, FLASH中运行的代码是 ACTIONSCRIPT, 它是一个脚本语言 .而这个语言是运行在FLASH内部的AVM2虚拟机 上的. 所以它的一些功能都需要经过, 语言解释成AVM2虚拟机字节码 ,然后AVM2运行字节码,最后由本地NATIVE语言 ,也就是本机2进制程序执行.虽然这解决了平台无关的问题,但是带 来一个副作用,就是比较慢,这就是为什么FLASH上一直没有杀手级应用的主要原因.
从本质上来说, 这是一个构架上的问题. 而Alchemy 的出现,从构架上,改进了这个问题,你可以使用C/C++编写核心,快速的算法,让AS3进行调用, 达到加速的目标 . 这在过去,你只能使用ADOVE提供给你的内置native 程序. 现在,你可以自己干这件事情了. 既解决了平台无关的问题,又解决了效率的问题,甚至可以利用FLASH本身几十亿现有的客户端的优势,解决了渠道问题.可以这样说, Alchemy 打开了一个前所未有的时代!
让我们看看 Alchemy 到底做什么. 从ADOBE的说明文档上可以看到, Alchemy 是一个 运行在低层的虚拟机 (Low Level Virtual Machine) ,他运行在AVM2之下. 那你又要问了.既然有了一个虚拟AVM2了,为什么还要一个LLVM? 其实, LLVM 将C/C++代码进行编译, 并且生成RISC-LIKE指令的字节码, 存储在缓冲区之中, 在FLASH运行开始的时候, 实时翻译成机器相关的本地代码 . 需要调用的时候是调用翻译之后的2进制本地代码.以此来提高整体速度.这就是LLVM的关键技术, 而运行时译 (Runtime-Compile) 这种技术有点像 .NET . 而这种LLVM和AVM2的区别是, AVM2实时解释运行脚本代码,LLVM 预编译本地运行 .可以这样认为 AVM2 是 JAVA虚拟机, LLVM是 .NET虚拟机.他们在构架上处于不同的层次,满足不同需求对速度的要求.
当生成编译完成后,字节码需要保存在一个缓冲区之内. 由于在框架之内需要和AVM2兼容,所以这个缓冲区,将以 AVM2能识别的BYTEARRAY 形式保存在内存之中. 即使使用反编译工具,反编译这个SWF文件,也看不到任何代码. 并且, alchemy自动生成一个 AS3的接口文件,以方便AS3程序进行调用 . 值得注意的是, 所有C/C++编译之后的数据,都以 SWC 函数库 的形式生成 , 用户可以在自己的工程里 IMPORT.经过使用后发现,由 Alchemy 生成的SWC文件是比较大, 比 C/C++源文件大的多.即使一个只有几十来行的纯C 功能,生成SWC后都会有100多KB. 参考ADOBE的文档上说, 编译C/C++的代码,会将C/C++所需要的所有库,比如C标准库 统统放到一个SWC里去,并且严格遵循POSIX标准. (可移植操作系统接口) 由于这种机制的存在, 我们甚至可以在C/C++里嵌入线程的支持, 来运行同步或者异步的功能. 从而弥补了FLASH是单线程这一不足! 这将是一件美妙的事情! 而本人认为,由于C/C++代码是公用一个C标准库的,所以只要SWC中的功能越多,那么从空间效率上就越是划算. 并且在目前的宽带之下,多个100来KB问题不是太大.
当然,安全问题,也是alchemy的重头戏, 我们知道, FLASH 对安全问题是有一套非常严格的措施的,比如访问本地资源后,就不能访问远程资源,访问这个域的资源后,就不能访问其他域的资源.如果你要访问,就要在另外 一个域上安装一个沙箱(SecurityBox)文件,才能顺利访问. 而alchemy将C/C++带入FLASH之中,而C/C++ 是否能坏了这个规矩,让应用程序出轨呢? 答案当然是否定的,一旦这个程序被调用之后,其C/C++程序被严格的运行在一LLVM上,LLVM作为一个代理机构,向上,提供了对C/C++的平台支 持,比如独立的内存空间,独立的堆栈空间,独立的线程管理机构,等等. 向下将2进制程序输送到 本机CPU进行执行 . 所以安全问题上是非常到位的, 所以对C/C++来说,只要LLVM环境没有提供的,它将永远访问不到.
Adobe已经对 alchemy 进行了比较深度的优化,并且我相信以后将继续下去.就从用户来说,由于有了alchemy 的出现,一些对速度要求较高的算法,都可以使用C/C++来代替 . 由于接口上都是AS3的接口,所以移植现有的程序将会非常轻松.比如目前游戏开发中广泛使用的那个BitmapData.CopyPixel 如果用C纯代码进行改写,那么速度将提高几十倍之多 .
总结. Alchemy 的出现,开启了一个全新的时代, 未来你将会发现网业上不再是简单画面,而是充满动态的不同的效果,给于用户全新的体验.随着LLVM提供的功能加多,比如将显卡硬件的功能作为一个抽象接 口提供给C/C++调用,那么将来UNREAL3出现在网页上,你千万不要惊奇.甚至WOW出现在网页上,你也不要惊奇. 因为新时代的门已经打开!
B. 安装配置教程
官方配置教程:Alchemy: Documentation: Getting Started
天地会配置教程:关于安装Adobe Alchemy的步骤和注意事项
牛牛猪研究所 配置教程:Introduction of Alchemy3D
我自己的配置教程,XP & VISTA配置验证通过:
1. Cygwin
a) Archive---------select ‘zip’
b) Devel-----------select ‘gcc-g++’
c) Perl--------------choose ‘install’
2. JDK
3. Flex SDK 3.2
4. Alchemy Toolkit
5. Copy ‘Flex Builder 3\sdks\3.2.0\bin’ to ‘c:\flex\bin’
6. Edit ‘c:\cygwin\etc\profile ’
source /cygdrive/c/alchemy/alchemy-setup
PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/alchemy/achacks:/cygdrive/c/flex/bin: $PATH
7. Open ‘cygwin’, input ’cd c:/alchemy’
8. Input ‘./config’
9. Input ‘source /cygwin/c/alchemy/alchemy-setup’
10. Input ‘alc-on’
11. Close ‘cygwin’
12. (Optional) edit ‘c:\alchemy\alchemy-setup’
Change
‘#export ADL=/path/to/fyou/bin/adl (or adl.exe)’
To
‘export ADL=/cygdrive/c/flex/bin/adl.exe’
13. (Optional) edit ‘c:\cygwin\etc\bash.bashrc’
Add
‘source /cygdrive/c/alchemy/alchemy-setup
PATH=$ALCHEMY_HOME/achacks:/cygdrive/c/flex/bin:$PATH
export PATH’
14. Edit ‘c:\alchemy\achacks\hacks.pl ’
Change
‘if (‘uname’=~/CYGWIN/)’
To
‘if (‘/bin/uname’=~/CYGWIN/)’
15. Edit ‘c:\cygwin\Cygwin.bat ’
‘@echo off
C:
set CYGWIN=tty notitle glob
set
PATH=%PATH%;c:\cygwin\bin;c:\cygwin\sbin;c:\cygwin\usr\bin;c:\cygwin\usr\sbin;c:\cygwin\usr\local\bin
set LD_LIBRARY_PATH=c:\cygwin\lib;c:\cygwin\usr\lib;c:\cygwin\usr\local\lib
chdir C:\cygwin\bin
bash –login -i’
16. Open ‘cygwin’, input ‘cd /cygdrive/c/alchemy/samples/stringecho/’
17. Input ‘alc-on’
18. Input ‘gcc stringecho.c –O3 –Wall –swc –o stringecho.swc ’
19. Flex use:
var loader:CLibInit = new CLibInit;
var lib:Object = loader.init();
trace(lib.echo(“foo”));
20. We must use Flash Player 10 .
ActionScript Project: Project-Properties-ActionScript Compiler-Additional compiler
arguments- “-target-player=10.0.12”
C. Alchemy: Documentation: Developing with Alchemy: Tools
D. Alchemy: Documentation: Developing with Alchemy: C API
E. Alchemy: Documentation: Developing with Alchemy: AS3 API
F. Alchemy: FAQ
1. What type of projects could benefit from Alchemy?
1. 使用Alchemy对什么项目有好处?
Alchemy is intended to be used with C/C++ libraries that have few operating system dependencies (较少操作系统依赖性). It is ideally suited for computation-intensive use cases (计算密集型使用例子), such as audio/video transcoding (视频/音频转码), data manipulation (数据处理), XML parsing (XML解析), cryptographic functions (加密/解密), image encoding (图像编码), PDF rendering (PDF呈现) or physics simulation (物理模拟).
2. Is Alchemy-compiled code faster than ActionScript 3.0?
2. Alchemy编译的代码比AS3运行快吗?
For computation-intensive use cases, such as audio encoding/decoding, data manipulation or cryptographic functions, performance of code ported using the Alchemy tool chain can be ten times faster or more than native ActionScript 3.0 and anywhere from 2-10 times slower than native C/C++ code .
3. Why can't the ActionScript compiler generate byte code that executes as quickly as Alchemy?
3. 为什么ASC生成的字节码运行速度没Alchemy生成的快?
Compiling with LLVM tools (included as part of Alchemy) allows compile and link time optimizations (允许编译链接时优化) to be applied that the ActionScript compiler does not use as yet. In addition, for operations involving ByteArrays there are opcodes that are optimized for performance (一些跟ByteArray相关的优化性能的指令), which the ActionScript compiler does not generate today.
4. What is LLVM?
4. 什么是LLVM?
LLVM is a set of tools for creating and manipulating "low level virtual machine " bytecode . LLVM includes gcc/g++ based front-ends for converting arbitrary C and C++ code to LLVM bytecode .
5. How does Alchemy work?
5. Alchemy是如何工作的?
Alchemy works by converting LLVM bytecode to ActionScript 3.0 (AS3) source through an Adobe-authored LLVM back-end. This AS3 source is then compiled using a special version of the ActionScript Compiler to ActionScript bytecode (ABC) .(一个特别版本的ASC)
6. Does ActionScript provide APIs or syntax that allow the opcodes in Flash Player 10 to be used from ActionScript programs?
6. AS有没有提供API允许Flash Player 10中的指令应用在原生AS程序里?
Alchemy uses a modified ASC that has an “in-line assembler” syntax (内联汇编) that allows the new opcodes to be used from ActionScript programs, however.
7. Are the new opcodes faster than new Vector data type in Flash Player 10?
7. Alchemy里的新指令有没有比Flash Player 10里的Vector类型执行速度快?
The new opcodes help implement the C memory model, an untyped linear array of bytes . Additionally, Vector operations have not been optimized as heavily in Flash Player 10 as have the new opcodes. Therefore an Alchemy program working on an array of C data may run faster than the corresponding ActionScipt program working on a Vector of ActionScript values.(所以new opcodes比Vector快)
On the other hand, the C program has very limited error checking (C语言没有多少错误检查机制), and C programs frequently have errors where they address memory outside the intended array. Accesses to ActionScript Vectors are, however, fully error checked. The error checking tends to make it less time consuming to develop ActionScript code than C code.(因为错误检查耗去了不少时间)
8. What are the compiler optimizations in LLVM that do not yet exist in ASC?
8. LLVM的编译器具有哪些原生ASC所没有的优化?
ASC performs few optimizations at this time, whereas LLVM performs many of the standard optimizations one would expect a C compiler to perform—including inlining, loop unrolling, strength reduction, and loop invariant code motion (各种优化的方面). Alchemy uses LLVM to optimize the code it generates , resulting in bytecode that is often better than that produced by ASC. but as a general rule the better bytecode generated by Alchemy allows AVM2 to produce faster machine code.(better bytecode better performance)
G. Understanding Adobe Alchemy
The big idea behind LLVM is that the core LLVM compiler will take code in many different languages and compile it into simple RISC-like instructions that are platform neutral (将各种语言编译成平台无关的RISC-like指令).
This is also why Alchemy generated SWCs are on the large side – they include everything that C or C++ may need such as the C standard library and POSIX support.(Alchemy生成的swc很大,因为它包含了所有的C标准库)
This is also why Alchemy can do things like its built-in “green threads” that let’s you run synchronous C asynchronously inside of the Flash Player .(让同步的C在异步的flash中使用)
When you instantiate your Alchemy compiled library, the code is allocating a nice chunk of memory into a ByteArray.(实例化Alchemy类库后,会派发一个内存块到ByteArray里)
This is how Alchemy takes pointers , malloc , free , etc and makes those concepts work in ActionScript.(Alchemy会使用指针,malloc和free操作内存)
In fact, because LLVM does a lot of optimizations , whereas Flash and Flex have no optimization step built into their compilers, Alchemy code manages to overcome a lot of it is overhead just on its own.(LLVM会做一些优化,这些优化是Flash和Flex没有的)
Now, what are these operations that Alchemy does so well? Memory access and function calls .Alchemy compiled code utilizes new bytecodes added to FP10 for working with ByteArrays – which as you’ll remember are what make up the “RAM” in Alchemy . Function calls are faster because in ActionScript function calls require that their parameters be “boxed” and “unboxed” into and out of objects for each call (AS函数调用需要对他们的参数进行“装箱”,“拆箱”操作,所以速度慢,而Alchemy函数调用就不要). Alchemy code doesn’t have to do this.
All of this speediness can be undone though by jumping back and forth between Alchemy code and regular ActionScript . This process is called marshaling and you’ll want to keep it to a minimum.Marshaling is expensive so you’ll want to try to create calls that stay in the C code as long as possible.(在AS与Alchemy之间频繁切换会增大开销) You’ll also want to try to limit the number of parameters you’re passing back and forth (it’s actually best to work directly with Alchemy’s “RAM” if possible).(减少传递参数的个数)
H. Adobe Alchemy, is it ActionScript heresy?
The magic of C64 Assembler
What I learned about that was that interpreted basic was a lot slower then assembler (解释指令比汇编指令慢) and if you wanted to get real speed you'd have to target the platforms native code.Assembler wasn't magic, it was just a better way to target the platform.
Back to current day.
It's an ironic name Adobe chose for FlaCC. There's a clear distinction between alchemy and science . Alchemy is most known for trying to create noble metals from otherwise less-valuable materials.(为什么Adobe要命名为Alchemy呢?炼金术有伪科学的意思,这真是一种讽刺)
Is it witchcraft ?
Something to do with reserving a block of memory .(进行内存块的一些操作)
So logically, one might asses that the best way to write code for the AVM2 is using ActionScript.(逻辑上,在AVM2上执行速度最快的应该是原生的AS3程序,而不是现在的Alchemy!)
Heresy I say! Heresy! Burn the witch!
This part of the API is not available from within ActionScript itself .So, the platform (AVM2) now has features which are not supported by the language which is native to it ? Wow. (这部分的API居然不能被AS本身使用!?)
If we have to let go of ActionScript to harness the pure speed Alchemy proofs is possible, then tell us. What is the future of our beloved language and our compilers for it ?
Adoeb Alchemy架构图:
官方视频中的截图:
自己细化的流程图:
几个牛人的例子 :
Flash 10, Massive amounts of 3D particles with Alchemy
More play with Alchemy: Lookup table effects
Another scream on Flash, Alchemy Memory and compilers
Alchemy plasma experiment (这个例子入门不错)
Using an Alchemy generated texture on a 3D object (接上个例子)