trace("Inside Tamarin::GC")
00:22 , Qizhi
Mozilla和Adobe在Tamarin的项目主页上没有多少文档,信息量其实少的可怜,绝大多数是要看源代码来理解的。其核心模块MMgc(垃圾回收)与Nanojit LIR(JIT编译器)也都是开源的,这为我们理解Actionscript3语言(语言相关的核心功能,显示与渲染相关的是闭源的,Adobe辩解说其中有H.264等视频专利授权的版权原因)有很大帮助。
要学好语言,最好的方法是自己去写一门语言。当然学写C++或Actionscript3就算了:)但是我们可以阅读他们。
在使用AS3写时,最需要关注的莫过于内存管理了。我们看看AVM+(Flash虚拟机)是如何管理内存的。AVM1代(Flash7之前)使用的是传统的引用计数算法(FIFE(www.fifengine.de)游戏引擎目前也采用的这种算法。这个算法类似这样:
这是最简单也最直观的回收算法了。当时的Micromedia工程师在没有压力的情况下,居然将这种算法用了7代,这是一种什么样的精神:) 引用技术算法最大的问题在于没法解决交叉引用的bug。比如A应用了B的同时,B也引用了A,那么这两个对象是永远无法被销毁的。AVM+改进了引用计数算法,是一种延期执行的引用计数算法,并且堆和栈的策略不同。首先栈里的数据进进出出,来的快死的也快,这里是没有也不需要任何引用计数策略的。引用计数只发生在堆-堆之间的引用中。网上流行的文章中,很多人批评Flash里的GC是发生在不可控制的时机的。在理解了MMgc的原理之后也许就不会有这样的质疑了。既然栈里的数据没有引用技术,那么当引用为0时立即清除会抛出一个悬摆指针。为了解决这个问题,MMgc选择将这些引用为0的对象暂时保存到一个列表(更确切的将,是一个散列表)ZCT中,当该表达到最大值时,会发生一次回收。此时MMgc会扫描栈,将未引用ZCT的数据杀掉,释放内存。
MMgc同时结合了另外一直垃圾回收的算法─标记清楚法,也是一种十分常见的GC算法。每一个对象都会包含一个标记位,在算法的第一阶段:标记阶段,由根节点开始扫描所有对象,将所有能抵达的对象标记一下,那么所有不能到达的对象即为可被回收对象。当然,这种算法针对不同的对象也采用不同的策略。
其他还有很多细节,比如内存分配的策略,每次可分配内存的大小等,可以查看Tamarin(https://developer.mozilla.org/en/Tamarin)相关文档,或直接看源代码。
MMgc是非常独立的一个模块,也就是说,如果要写C++有希望能引入GC,那么选择这个开源库是不错的。唯一要注意的是协议采用了MPL/GPL/LGPL,商业应用可以选择MPL以避免GPL的感染。
一家之言,非Adobe官方文档,如有不当,还请指正。
要学好语言,最好的方法是自己去写一门语言。当然学写C++或Actionscript3就算了:)但是我们可以阅读他们。
在使用AS3写时,最需要关注的莫过于内存管理了。我们看看AVM+(Flash虚拟机)是如何管理内存的。AVM1代(Flash7之前)使用的是传统的引用计数算法(FIFE(www.fifengine.de)游戏引擎目前也采用的这种算法。这个算法类似这样:
Object() { refCount = 0; }
void AddRef() { refCount++; }
void Release() {
if (!--refCount) delete this;
}
void AddRef() { refCount++; }
void Release() {
if (!--refCount) delete this;
}
这是最简单也最直观的回收算法了。当时的Micromedia工程师在没有压力的情况下,居然将这种算法用了7代,这是一种什么样的精神:) 引用技术算法最大的问题在于没法解决交叉引用的bug。比如A应用了B的同时,B也引用了A,那么这两个对象是永远无法被销毁的。AVM+改进了引用计数算法,是一种延期执行的引用计数算法,并且堆和栈的策略不同。首先栈里的数据进进出出,来的快死的也快,这里是没有也不需要任何引用计数策略的。引用计数只发生在堆-堆之间的引用中。网上流行的文章中,很多人批评Flash里的GC是发生在不可控制的时机的。在理解了MMgc的原理之后也许就不会有这样的质疑了。既然栈里的数据没有引用技术,那么当引用为0时立即清除会抛出一个悬摆指针。为了解决这个问题,MMgc选择将这些引用为0的对象暂时保存到一个列表(更确切的将,是一个散列表)ZCT中,当该表达到最大值时,会发生一次回收。此时MMgc会扫描栈,将未引用ZCT的数据杀掉,释放内存。
MMgc同时结合了另外一直垃圾回收的算法─标记清楚法,也是一种十分常见的GC算法。每一个对象都会包含一个标记位,在算法的第一阶段:标记阶段,由根节点开始扫描所有对象,将所有能抵达的对象标记一下,那么所有不能到达的对象即为可被回收对象。当然,这种算法针对不同的对象也采用不同的策略。
其他还有很多细节,比如内存分配的策略,每次可分配内存的大小等,可以查看Tamarin(https://developer.mozilla.org/en/Tamarin)相关文档,或直接看源代码。
MMgc是非常独立的一个模块,也就是说,如果要写C++有希望能引入GC,那么选择这个开源库是不错的。唯一要注意的是协议采用了MPL/GPL/LGPL,商业应用可以选择MPL以避免GPL的感染。
一家之言,非Adobe官方文档,如有不当,还请指正。
May
13
2010
用遗传算法让电脑写宋词
23:34 , Qizhi
引用
相逢缥缈,窗外又拂晓.长忆清弦弄浅笑,只恨人间花少.
黄菊不待清尊,相思飘落无痕.风雨重阳又过,登高多少黄昏.
黄菊不待清尊,相思飘落无痕.风雨重阳又过,登高多少黄昏.
这首《清平乐.黄菊》的作者是一台计算机,比我写的好,十分佩服。且平仄、押韵十分工整,没有明显的句法错误,没有读着别扭的句子,风格婉约,伤感悲秋。这还是一台CPU 1.83GHz,内存512M计算机么?看完《一种宋词自动生成的遗传算法及其机器实现》这篇论文后,我对诗人、艺术家们十分同情,会有一天他们下岗的。
除了对人类未来的担忧,我感兴趣的是研究者们解决问题的思路。我们这样分析:
1. 基于统计学的词库。虽说汉语常用词汇不过3千个,可是这些词放在不同的上下文中所能表达的意思确千差万别。登山则情满于山,观海则意溢于海,人类的语言是人类情感的抒发。我认为要让计算机写诗,最基础的工作就是建立一个包含情感类别、语义、音韵等要素的元数据库。
2. 填词的过程是搜索的过程。回想高中学写宋词的时候,总是安装词牌的要求一个一个词的填写,这是从大脑中搜索的过程,对于计算机而言是一个类似的过程。我们可以采用启发式搜索,使得搜索总是沿着较优的方向前进。可以根据词法等相关概念,从词库挑选一系列备用词,沿着计算出来的评价(打分)进行搜索。
这篇论文和我前段时间读的人工鱼模拟的的论文类似,在解决搜索问题上都使用了遗传算法。遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法(引:百度百科)。
这是一篇很有意思的论文,所以我写了些自己的想法。语义分析我不懂也不是很感兴趣,但是,通过读论文来开拓视野,长长见识,推荐大家多逛逛相关网站:)
May
9
2010
Flash中是没有Byte类型的。ByteArray却可以读取字节流。存储在ByteArray中的自然是Byte,那么,其Write/Read Byte的方法是怎么回事?
Write:The low 8 bits of the parameter are used. The high 24 bits are ignored."
是的,Int的低8位被写入,剩余24位被忽略。ReadByte返回的是一个int,The returned value is in the range -128 to 127,即{-27, 27-1}。这里的定义与Java中Byte类型定义相同,是8位有符号整数。
然而事实情况很玄妙,不通过readByte来读取,而是直接通过index读取各个位的值,获取的数值是0到255的8位无符号整数(补码存储,买个关子,想知道原因的同学请Google之)。如果有人要写一些底层数据或者是移植工作,切记!如有谬误,请指正。
相关代码:
Write:The low 8 bits of the parameter are used. The high 24 bits are ignored."
是的,Int的低8位被写入,剩余24位被忽略。ReadByte返回的是一个int,The returned value is in the range -128 to 127,即{-27, 27-1}。这里的定义与Java中Byte类型定义相同,是8位有符号整数。
然而事实情况很玄妙,不通过readByte来读取,而是直接通过index读取各个位的值,获取的数值是0到255的8位无符号整数(补码存储,买个关子,想知道原因的同学请Google之)。如果有人要写一些底层数据或者是移植工作,切记!如有谬误,请指正。
相关代码:
var byte:ByteArray = new ByteArray();
byte.writeInt(255); //byte.writeInt(256); 127, 128, -1, -128,etc
var arr:Array = [];
for(var i:int = 0; i < byte.length; i++)
{
arr[i] = byte[i];
}
trace(arr);
byte.writeInt(255); //byte.writeInt(256); 127, 128, -1, -128,etc
var arr:Array = [];
for(var i:int = 0; i < byte.length; i++)
{
arr[i] = byte[i];
}
trace(arr);
Apr
24
2010
峰会PPT: Flash游戏人工智能
22:23 , Qizhi
很荣幸受邀参加了adobe平台技术峰会,我是今天早晨9点的演讲,主要总结了些游戏开发入门的知识,感谢诸位冒雨捧场:)
另外,还是我演讲最后的广告:我们在招兵买马,求贤若渴。雏鹰虽小,志向远大,我们立志成为全球Social Game顶尖公司。目前《开心水族箱》在Facebook拥有超过250万的日活跃,第二款游戏在登陆Facebook后,并获得了日本最大的SNS网站Mixi的官方肯定与推荐。不论是Java/C++,还是PHP,不论是设计师还是DBA,又或是刚刚踏出学校学子,我们都虚位以待,详情:
1 Flash游戏开发工程师
2 软件架构师
3 Mysql DBA
4 Java 游戏后台开发工程师
5 数据分析工程师
7 设计师
8 游戏策划
关于Flash游戏开发工程师,我多说一句。我们看重的并不是您对Adobe相关技术的掌握程度,而是您对计算机,对程序设计的理解力和对游戏开发的激情。所以哪怕您对Flash一窍不通,哪怕您只会写PHP,只要您喜欢游戏客户端开发,喜欢图形技术,喜欢AI,那么,加入我们吧。我们的团队有来自微软的顶尖架构师,有资深的游戏设计师,有来自校内、Myspace熟悉SNS的同事,也有早期互联网的创业人员与商务头脑。 与这样一群人共事,何乐而不为呢?
我的邮箱:ezhung [at] gmail.com
HappylEments工作环境:

我的工位

MM的工位
另外,还是我演讲最后的广告:我们在招兵买马,求贤若渴。雏鹰虽小,志向远大,我们立志成为全球Social Game顶尖公司。目前《开心水族箱》在Facebook拥有超过250万的日活跃,第二款游戏在登陆Facebook后,并获得了日本最大的SNS网站Mixi的官方肯定与推荐。不论是Java/C++,还是PHP,不论是设计师还是DBA,又或是刚刚踏出学校学子,我们都虚位以待,详情:
1 Flash游戏开发工程师
2 软件架构师
3 Mysql DBA
4 Java 游戏后台开发工程师
5 数据分析工程师
7 设计师
8 游戏策划
关于Flash游戏开发工程师,我多说一句。我们看重的并不是您对Adobe相关技术的掌握程度,而是您对计算机,对程序设计的理解力和对游戏开发的激情。所以哪怕您对Flash一窍不通,哪怕您只会写PHP,只要您喜欢游戏客户端开发,喜欢图形技术,喜欢AI,那么,加入我们吧。我们的团队有来自微软的顶尖架构师,有资深的游戏设计师,有来自校内、Myspace熟悉SNS的同事,也有早期互联网的创业人员与商务头脑。 与这样一群人共事,何乐而不为呢?
我的邮箱:ezhung [at] gmail.com
AI in flash games
View more presentations from qizhi20.
HappylEments工作环境:

我的工位

MM的工位
Apr
22
2010
下面的代码十分困惑:
var re:URLRequest = new URLRequest("http://www.***.com");
re.method = URLRequestMethod.POST;
var byte:ByteArray = new ByteArray();
byte.writeUTF("hi");
byte.writeUTF("why");
byte.writeInt(1);
var obj:Object = {};
obj.a = 1;
obj.b = "hi";
byte.writeObject(obj);
re.data = byte;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(re);
按预测,URLRequest在post ByteArray数据时会按照其默认编码(AMF3)序列化,但事实情况是,只有代码中Object对应的字段被准确序列化,而int,String等值对象被序列化后掩码错误。上述代码抓包数据:
数据中的"|"为我加入的分格符号。可以看出,String被序列化后由长度+正文组成,但是掩码(marker)是文档中定义的undefined-marker(int的掩码也被错误的写为0x00),即0x00.唯独Object的掩码是正常的0x0A,并且其属性a与b的值的掩码是均是正确的0x04与0x06.
不解?...
var re:URLRequest = new URLRequest("http://www.***.com");
re.method = URLRequestMethod.POST;
var byte:ByteArray = new ByteArray();
byte.writeUTF("hi");
byte.writeUTF("why");
byte.writeInt(1);
var obj:Object = {};
obj.a = 1;
obj.b = "hi";
byte.writeObject(obj);
re.data = byte;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(re);
按预测,URLRequest在post ByteArray数据时会按照其默认编码(AMF3)序列化,但事实情况是,只有代码中Object对应的字段被准确序列化,而int,String等值对象被序列化后掩码错误。上述代码抓包数据:
00 02 68 69 | 00 03 77 68 | 79 00 00 00 | 01 0A 0B 01 | 03 61 04 01 | 03 62 06 05 | 68 69 01
数据中的"|"为我加入的分格符号。可以看出,String被序列化后由长度+正文组成,但是掩码(marker)是文档中定义的undefined-marker(int的掩码也被错误的写为0x00),即0x00.唯独Object的掩码是正常的0x0A,并且其属性a与b的值的掩码是均是正确的0x04与0x06.
不解?...
Apr
11
2010




