- 浏览: 1088080 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (695)
- 心情日记 (14)
- AS开发工具 (12)
- 文章转载 (99)
- AIR (5)
- 问题总结 (46)
- SWF格式 (7)
- 测试总结 (10)
- 外文资料 (9)
- 算法技术 (33)
- AS3常用开源库 (43)
- 源码范例 (102)
- FLEX (72)
- FLASH 优化 (33)
- 游戏开发 (49)
- 开发技术 (11)
- 工作应用 (34)
- AS3收集 (140)
- WebBase (0)
- 开发构想 (4)
- 设计模式 (2)
- 框架和框架范例 (19)
- RED5 (3)
- java开发 (3)
- JAVA (1)
- FLASH-3D (23)
- 3D (6)
- 书籍 (10)
- 业界信息资料 (3)
- C# (1)
- JavaScript (12)
- HTML5 (6)
- Flixel (1)
- D5Power RPG网页游戏引擎 (0)
- ColorMatrixFilter - 获得相应颜色的色调 函数 (0)
- Starling (0)
最新评论
-
老顽童203:
字体
水果忍者鼠标跟随特效制作[转载] -
hairball00:
[转] 放出超多的Flash组件源代码 -
he74552775:
flash AS3 RegExp简单功能用法(转) -
hanshuai1232000:
第四点,有利也有弊,等你做了大型的aprg,你就知道了
[转]位图数据内存优化 -
yangfantao:
太感谢
[转] 放出超多的Flash组件源代码
http://jacksondunstan.com/articles/573
I’ve previously covered ways of implementing in my article on Runnables (aka observers) which showed how to call back about 15 times faster than just using a Function object. There are still more ways to call back though and I didn’t cover them at the time. Today I’ll be adding to Function and Runnables by testing Event and the as3signals library by Robert Penner.
As you most certainly know, AS3′s ubiquitous Event class is a way of call back a whole collection of functions at the same time. These have numerous problems ranging from performance to object allocation and garbage collection to more stylistic concerns. This prompted Robert Penner to create the as3signals system as a replacement for Events. Today I will test both as3signals and Events against simple Vectors of Functions and Runnables. I will also test as3signals and Events against a single Function and a single Runnable. The purpose of this is to show how various levels of complexity and features affect performance. Clearly as3signals and Event are far more advanced than a single callback or a simple Vector of callbacks, but sometimes that’s all you need. That said, let’s take a look at the test app:
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;
import org.osflash.signals.*;
[SWF(backgroundColor=0xEEEADB,frameRate=1000)]
/**
* A test of various callback techniques
* @author Jackson Dunstan
*/
public class CallbacksTest extends Sprite
{
public var signal:Signal;
public var funcs:Vector.<Function> = new Vector.<Function>();
public var runnables:Vector.<Runnable> = new Vector.<Runnable>();
public function CallbacksTest()
{
var logger:TextField = new TextField();
logger.autoSize = TextFieldAutoSize.LEFT;
addChild(logger);
this.signal = new Signal();
var i:int;
const FUNC_CALL_REPS:int = 1000000;
const NUM_LISTENERS:int = 10;
const EVENT_TYPE:String = "test";
var runnable:Runnable = new MyRunnable();
var func:Function = runnable.run;
// Single call
var beforeTime:int = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
func();
}
logger.appendText("Func call time: " + (getTimer()-beforeTime) + "\n");
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
runnable.run();
}
logger.appendText("Runnable call time: " + (getTimer()-beforeTime) + "\n");
addEventListener(EVENT_TYPE, onEvent0);
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchEvent(new Event(EVENT_TYPE));
}
logger.appendText("Event (1 listener) time: " + (getTimer()-beforeTime) + "\n");
removeEventListener(EVENT_TYPE, onEvent0);
this.signal.add(onSignal0);
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
this.signal.dispatch();
}
logger.appendText("Signal (1 listener) time: " + (getTimer()-beforeTime) + "\n\n");
this.signal.remove(onSignal0);
// Calling a list
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.funcs.push(func);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchFuncs(this.funcs);
}
logger.appendText("Func call (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.runnables.push(runnable);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchRunnables(this.runnables);
}
logger.appendText("Runnable call (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
addEventListener(EVENT_TYPE, this["onEvent"+i]);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchEvent(new Event(EVENT_TYPE));
}
logger.appendText("Event (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.signal.add(this["onSignal"+i]);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
this.signal.dispatch();
}
logger.appendText("Signal (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
}
private function dispatchFuncs(funcs:Vector.<Function>): void
{
var len:int = funcs.length;
for (var i:int = 0; i < len; ++i)
{
funcs[i]();
}
}
private function dispatchRunnables(runnables:Vector.<Runnable>): void
{
var len:int = runnables.length;
for (var i:int = 0; i < len; ++i)
{
Runnable(runnables[i]).run();
}
}
private function onEvent0(ev:Event): void {}
private function onEvent1(ev:Event): void {}
private function onEvent2(ev:Event): void {}
private function onEvent3(ev:Event): void {}
private function onEvent4(ev:Event): void {}
private function onEvent5(ev:Event): void {}
private function onEvent6(ev:Event): void {}
private function onEvent7(ev:Event): void {}
private function onEvent8(ev:Event): void {}
private function onEvent9(ev:Event): void {}
private function onSignal0(): void {}
private function onSignal1(): void {}
private function onSignal2(): void {}
private function onSignal3(): void {}
private function onSignal4(): void {}
private function onSignal5(): void {}
private function onSignal6(): void {}
private function onSignal7(): void {}
private function onSignal8(): void {}
private function onSignal9(): void {}
}
}
internal interface Runnable
{
function run(): void;
}
internal class MyRunnable implements Runnable
{
public function run(): void {}
}
Here are the results I get for the single listener versions:
ENVIRONMENT FUNC (1) RUNNABLE (1) EVENT (1) SIGNAL (1)
3.0 Ghz Intel Core 2 Duo, 4GB, Windows XP 67 4 1336 1412
2.0 Ghz Intel Core 2 Duo, 4GB, Mac OS X 10.5 90 7 6108 2275
2.2 Ghz Intel Core 2 Duo, 2GB, Mac OS X 10.6 82 6 5115 2057
And here are the results for the multiple-listener versions:
ENVIRONMENT FUNC (10) RUNNABLE (10) EVENT (10) SIGNAL (10)
3.0 Ghz Intel Core 2 Duo, 4GB, Windows XP 668 180 2877 2804
2.0 Ghz Intel Core 2 Duo, 4GB, Mac OS X 10.5 964 342 38643 4314
2.2 Ghz Intel Core 2 Duo, 2GB, Mac OS X 10.6 880 311 31512 3958
The above table shows that we don’t quite have a separation between the single listener tests and the multiple listener tests, which is rather disappointing. The single Runnable test is shockingly fast compared to as3signals (300x slower) and Event (300x slower on Windows, 600x slower on Mac). However, as pointed out above, these systems are much more complex and have many more features than a single callback. Event, for example, requires allocating a new Event object and supports such advanced features as bubbling, canceling, and multiple listening functions. This is also true in a comparison of a simple Function object to either the as3signals or Event system. So, assuming you need that extra power and can’t get by with just a simple callback, let’s move on to where as3signals and Event are more justified: multiple callbacks.
Here we see the winner again is a Vector of Runnables, which beats out second place Vector of Functions by about three-to-one. Then come Event and as3signals, which are practically the same speed on Windows, but as3signals is about 10x faster on Mac. This is good news for those desiring an arguably-cleaner interface than Event presents and also good news for those hoping for a speed boost by using as3signals on a Mac, but not Windows. On the contrary, it’s good news for those with significant investments in the Event system who are only targeting Windows performance: there’s no need to re-write using as3signals to get a speedup so long as you keep to Windows. You might, rather, re-write to use a Vector of Runnables though if you’re interested in a a 15x speedup on Windows and 15-100x speedup on Mac.
What you’d lose in the process of converting from Event or as3signals to a simpler approach like a Vector of Runnables is a lot of the sophistication of those approaches. You’ll lose the aforementioned bubbling and canceling, some safety regarding changes to the Vector during a dispatch operation, type safety in the case of as3signals, consistency with the Flash API in the case of the Event system, and likely many more niceties. What you gain is raw speed. Only you can choose the appropriate system for you application.
Tags: callbacks, events, functions, performance, runnables, signals
I’ve previously covered ways of implementing in my article on Runnables (aka observers) which showed how to call back about 15 times faster than just using a Function object. There are still more ways to call back though and I didn’t cover them at the time. Today I’ll be adding to Function and Runnables by testing Event and the as3signals library by Robert Penner.
As you most certainly know, AS3′s ubiquitous Event class is a way of call back a whole collection of functions at the same time. These have numerous problems ranging from performance to object allocation and garbage collection to more stylistic concerns. This prompted Robert Penner to create the as3signals system as a replacement for Events. Today I will test both as3signals and Events against simple Vectors of Functions and Runnables. I will also test as3signals and Events against a single Function and a single Runnable. The purpose of this is to show how various levels of complexity and features affect performance. Clearly as3signals and Event are far more advanced than a single callback or a simple Vector of callbacks, but sometimes that’s all you need. That said, let’s take a look at the test app:
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;
import org.osflash.signals.*;
[SWF(backgroundColor=0xEEEADB,frameRate=1000)]
/**
* A test of various callback techniques
* @author Jackson Dunstan
*/
public class CallbacksTest extends Sprite
{
public var signal:Signal;
public var funcs:Vector.<Function> = new Vector.<Function>();
public var runnables:Vector.<Runnable> = new Vector.<Runnable>();
public function CallbacksTest()
{
var logger:TextField = new TextField();
logger.autoSize = TextFieldAutoSize.LEFT;
addChild(logger);
this.signal = new Signal();
var i:int;
const FUNC_CALL_REPS:int = 1000000;
const NUM_LISTENERS:int = 10;
const EVENT_TYPE:String = "test";
var runnable:Runnable = new MyRunnable();
var func:Function = runnable.run;
// Single call
var beforeTime:int = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
func();
}
logger.appendText("Func call time: " + (getTimer()-beforeTime) + "\n");
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
runnable.run();
}
logger.appendText("Runnable call time: " + (getTimer()-beforeTime) + "\n");
addEventListener(EVENT_TYPE, onEvent0);
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchEvent(new Event(EVENT_TYPE));
}
logger.appendText("Event (1 listener) time: " + (getTimer()-beforeTime) + "\n");
removeEventListener(EVENT_TYPE, onEvent0);
this.signal.add(onSignal0);
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
this.signal.dispatch();
}
logger.appendText("Signal (1 listener) time: " + (getTimer()-beforeTime) + "\n\n");
this.signal.remove(onSignal0);
// Calling a list
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.funcs.push(func);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchFuncs(this.funcs);
}
logger.appendText("Func call (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.runnables.push(runnable);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchRunnables(this.runnables);
}
logger.appendText("Runnable call (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
addEventListener(EVENT_TYPE, this["onEvent"+i]);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
dispatchEvent(new Event(EVENT_TYPE));
}
logger.appendText("Event (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
for (i = 0; i < NUM_LISTENERS; ++i)
{
this.signal.add(this["onSignal"+i]);
}
beforeTime = getTimer();
for (i = 0; i < FUNC_CALL_REPS; ++i)
{
this.signal.dispatch();
}
logger.appendText("Signal (" + NUM_LISTENERS + " listeners) time: " + (getTimer()-beforeTime) + "\n");
}
private function dispatchFuncs(funcs:Vector.<Function>): void
{
var len:int = funcs.length;
for (var i:int = 0; i < len; ++i)
{
funcs[i]();
}
}
private function dispatchRunnables(runnables:Vector.<Runnable>): void
{
var len:int = runnables.length;
for (var i:int = 0; i < len; ++i)
{
Runnable(runnables[i]).run();
}
}
private function onEvent0(ev:Event): void {}
private function onEvent1(ev:Event): void {}
private function onEvent2(ev:Event): void {}
private function onEvent3(ev:Event): void {}
private function onEvent4(ev:Event): void {}
private function onEvent5(ev:Event): void {}
private function onEvent6(ev:Event): void {}
private function onEvent7(ev:Event): void {}
private function onEvent8(ev:Event): void {}
private function onEvent9(ev:Event): void {}
private function onSignal0(): void {}
private function onSignal1(): void {}
private function onSignal2(): void {}
private function onSignal3(): void {}
private function onSignal4(): void {}
private function onSignal5(): void {}
private function onSignal6(): void {}
private function onSignal7(): void {}
private function onSignal8(): void {}
private function onSignal9(): void {}
}
}
internal interface Runnable
{
function run(): void;
}
internal class MyRunnable implements Runnable
{
public function run(): void {}
}
Here are the results I get for the single listener versions:
ENVIRONMENT FUNC (1) RUNNABLE (1) EVENT (1) SIGNAL (1)
3.0 Ghz Intel Core 2 Duo, 4GB, Windows XP 67 4 1336 1412
2.0 Ghz Intel Core 2 Duo, 4GB, Mac OS X 10.5 90 7 6108 2275
2.2 Ghz Intel Core 2 Duo, 2GB, Mac OS X 10.6 82 6 5115 2057
And here are the results for the multiple-listener versions:
ENVIRONMENT FUNC (10) RUNNABLE (10) EVENT (10) SIGNAL (10)
3.0 Ghz Intel Core 2 Duo, 4GB, Windows XP 668 180 2877 2804
2.0 Ghz Intel Core 2 Duo, 4GB, Mac OS X 10.5 964 342 38643 4314
2.2 Ghz Intel Core 2 Duo, 2GB, Mac OS X 10.6 880 311 31512 3958
The above table shows that we don’t quite have a separation between the single listener tests and the multiple listener tests, which is rather disappointing. The single Runnable test is shockingly fast compared to as3signals (300x slower) and Event (300x slower on Windows, 600x slower on Mac). However, as pointed out above, these systems are much more complex and have many more features than a single callback. Event, for example, requires allocating a new Event object and supports such advanced features as bubbling, canceling, and multiple listening functions. This is also true in a comparison of a simple Function object to either the as3signals or Event system. So, assuming you need that extra power and can’t get by with just a simple callback, let’s move on to where as3signals and Event are more justified: multiple callbacks.
Here we see the winner again is a Vector of Runnables, which beats out second place Vector of Functions by about three-to-one. Then come Event and as3signals, which are practically the same speed on Windows, but as3signals is about 10x faster on Mac. This is good news for those desiring an arguably-cleaner interface than Event presents and also good news for those hoping for a speed boost by using as3signals on a Mac, but not Windows. On the contrary, it’s good news for those with significant investments in the Event system who are only targeting Windows performance: there’s no need to re-write using as3signals to get a speedup so long as you keep to Windows. You might, rather, re-write to use a Vector of Runnables though if you’re interested in a a 15x speedup on Windows and 15-100x speedup on Mac.
What you’d lose in the process of converting from Event or as3signals to a simpler approach like a Vector of Runnables is a lot of the sophistication of those approaches. You’ll lose the aforementioned bubbling and canceling, some safety regarding changes to the Vector during a dispatch operation, type safety in the case of as3signals, consistency with the Flash API in the case of the Event system, and likely many more niceties. What you gain is raw speed. Only you can choose the appropriate system for you application.
Tags: callbacks, events, functions, performance, runnables, signals
发表评论
-
柔软的带弹性的物理体验js源码和as源码
2011-09-08 01:41 0柔软的带弹性的物理体验js源码和as源码 -
[转]理解Flash Player 10.1和AIR 2中的安全更改
2011-08-10 15:21 1305http://www.infoq.com/cn/vendorc ... -
愤怒的小鸟 BOX2D FLASH
2011-08-09 01:27 0姊妹篇:Flash版《植物大战僵尸》源码今年就要大四啦,放暑假 ... -
[转]PT与PX区别
2011-08-01 00:43 1376http://blog.sina.com.cn/s/blog_ ... -
[转]一个Collision类,其中的block方法可以实现两个物体之间的碰撞检测。
2011-07-30 02:35 1399第二个是书中的源代码给出了一个Collision类,其中 ... -
Color depth change
2011-07-28 00:10 1523http://en.nicoptere.net/?p=8 ... -
AIR2.6以后flash player对图片的解码并非异步的
2011-07-14 19:54 0http://www.5uflash.com/flashjia ... -
[转] <What can you do with bytes ?> 第二章 第一节: 对象的复制
2011-03-16 00:07 1024http://bbs.9ria.com/viewthread. ... -
ActionScript Collections and Functional Programming
2011-03-13 20:18 900http://www.artima.com/weblogs/v ... -
Object Pooling in AS3
2011-01-12 11:56 1123If you're looking to save me ... -
[转]Asynchronous ActionScript Execution
2010-09-25 14:31 1392地址: http://www.senocular.com/fl ...
相关推荐
易语言Callback数据类型转易语言子程序源码.rar 易语言Callback数据类型转易语言子程序源码.rar 易语言Callback数据类型转易语言子程序源码.rar 易语言Callback数据类型转易语言子程序源码.rar 易语言Callback...
标题提到的“Callback数据类型转易语言子程序”实际上是在探讨如何在易语言中模拟回调机制,通过将函数指针或者某种标识作为参数传递,从而在需要的时候调用该函数。 具体实现方式可能包括以下几种: 1. **使用...
用友U9客户化开发 Callback & Postback 入门 v0.8 用友U9客户化开发 Callback & Postback 入门 v0.8 是一份关于用友U9客户化开发中 Callback 和 Postback 的基础知识入门文档。该文档详细介绍了 Callback 和 ...
**VC++ CALLBACK** 在Microsoft Visual C++(简称VC++)编程中,回调函数是一种机制,允许我们传递一个函数作为参数给另一个函数,然后在需要的时候由这个接收函数调用我们传入的函数。这种功能在处理异步操作、...
本文将深入探讨如何利用OkHttp进行网络请求,并封装两种Callback处理方式:一种是返回String类型,后续在子类进行JSON解析;另一种则是直接传入泛型的JavaBean,完成解析后再传回子类。 首先,了解OkHttp的基本用法...
本主题主要探讨的是如何基于鸿洋的OkHttpUtils进行数据Bean的封装以及Callback回调的处理。 首先,我们来理解一下OkHttpUtils的核心概念。OkHttpUtils提供了一系列静态方法,如`get()`, `post()`等,用于发起HTTP...
本文实例分析了C++中回调函数(CallBack)的用法。分享给大家供大家参考。具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。 其错误是普通的C++成员函数都隐含了一个传递...
"Callback数据类型转易语言子程序源码"这个压缩包文件,很可能是包含了一组易语言源代码,用于演示或教学如何将Callback数据类型转换为易语言的子程序。这样的转换可能涉及到以下几个步骤: 1. **定义Callback数据...
本篇文章将详细解释如何在C语言环境中使用protobuf-c处理`repeated`字段,创建数组和字符串,并特别关注`pb_callback_t`这一特殊类型。 首先,我们需要理解`repeated`字段在protobuf语义中的含义。在protobuf的定义...
这是一个及其简单的但是又实用的callBack
回调(Callback)是一种在软件设计模式中常见的编程概念,它允许一个函数或对象在完成某个操作后通知另一个函数或对象。在本示例"CallBack_DEMO"中,我们可能正在探讨如何在Java或其他编程语言中实现回调机制。回调...
**Delphi DataSnap CallBack 知识点详解** 在Delphi开发环境中,DataSnap是一个强大的技术,用于构建分布式应用程序,特别是在实现服务器与客户端之间的数据交换和远程方法调用(Remote Method Invocation, RMI)时...
**C# WCF CallBack Demo** Windows Communication Foundation (WCF) 是.NET Framework中用于构建分布式应用程序的服务模型。在WCF中,回调(Callback)是一种高级通信模式,它允许服务主动向客户端发送数据,而不...
在IT行业中,回调(Callback)是一种常见的编程技术,特别是在客户端-服务器交互中。本文将深入探讨标题中的"Callback"主题,结合C#语言和Windows Service服务程序,以及进程间通信(Inter-Process Communication, ...
回调技术(Callback)是软件设计模式中的一种,它在异步编程或事件驱动编程中扮演着重要角色。回调函数是一种代码执行模式,允许一个函数或方法在特定事件发生时被另一个函数调用。这种机制使得程序能够以非阻塞的...
callback
json+callback实现无刷新demo,短小精悍
回调(Callback)是一种在软件设计模式中常见的编程概念,它允许一个对象在完成特定操作后通知另一个对象。在Java或Android开发中,回调机制经常用于处理异步操作,例如网络请求、文件读写等,当操作完成时,通过回...
在给定的压缩包文件`callback_proc.rar_callback`中,包含了一个名为`callback_proc.c`的源代码文件,这很可能是实现NFSv4回调功能的具体代码。 NFSv4 Callbacks的主要目的是在客户端和服务器之间提供一种异步通信...
在这个例子中,`py_callback`是我们的Python回调函数,`wrap_callback`是一个Cython函数,它调用了C函数`cy_callback`。`use_callback`函数接受一个Python回调函数,并将其转换为C函数指针,然后传递给`wrap_...