Flash/Actionscript CPU 分析器 [英] Flash / Actionscript CPU profiler

查看:20
本文介绍了Flash/Actionscript CPU 分析器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你找到这样的工具并成功使用了吗?

Have you found such a tool and used it successfully?

推荐答案

我也在寻找 AS 的分析器,但我想要一个与 FlashDevelop 和 Flex SDK 配合使用的免费软件/开源解决方案.我没有找到.所以我写了一个简单的python脚本和一个更简单的AS类.该脚本基本上采用任何 AS 文件并添加分析代码(即以 1 毫秒的精度测量该函数的总运行时间的调用 - flash.utils.getTimer() 调用的分辨率)到每个函数定义.脚本有时会出错,但这些通常很容易手动修复.然后您需要手动再添加一行:在某个时候将分析统计信息转储到某处.这种方法显然不够准确,但它仍然让您对代码中的瓶颈有很好的感觉.我成功地将其用于 100k 文件.

I was also looking for a profiler for AS, but I wanted an freeware/open source solution that works with FlashDevelop and Flex SDK. I found none. So I wrote a simple python script and an even simpler AS class. The script essentially takes any AS file and adds profiling code (i.e. calls to measure the total runtime of that function with an accuracy of 1 ms - the resolution of the flash.utils.getTimer() call) to each function definition. The script sometimes makes mistakes, but these are usually easy to fix by hand. Then you need to add one more line manually: dump the profiling statistics somewhere at some point. This method is obviously far from accurate, but it nonetheless gives you good feel of bottlenecks in your code. I used it for a 100k file with success.

这是AS类:

package  {
    public class Profiler {
        private static var instance:Profiler;

        public static function get profiler():Profiler {
            if (!Profiler.instance) Profiler.instance = new Profiler;
            return Profiler.instance;
        }

        private var data:Object = {};

        public function profile(fn:String, dur:int):void {
            if (!data.hasOwnProperty(fn)) data[fn] = new Number(0);
            data[fn] += dur / 1000.0;
        }

        public function clear():void {
            data = { };
        }

        public function get stats():String {
            var st:String = "";
            for (var fn:String in data) {
                st += fn + ":	" + data[fn] + "
";
            }
            return st;
        }
    }
}

这里是执行此操作的 python 脚本:

And here is the python script that does the trick:

import sre, sys

rePOI = sre.compile(r'''class|function|return|["'/{}]''')
reFun = sre.compile(r'functions*((?:[gs]ets+)?w*)s*(')
reCls = sre.compile(r'classs+(w+)[s{]')
reStr = sre.compile(r'''(["'/]).*?(?<!\)1''')

def addProfilingCalls(body):
    stack = []
    pos = 0
    depth = 0
    retvar = 0
    klass = ""
    match = rePOI.search(body, pos)
    while match:
        poi = match.group(0)
        pos = match.start(0)
        endpos = match.end(0)

        if poi in '''"'/''':
            strm = reStr.match(body, pos)
            if strm and (poi != '/' or sre.search('[=(,]s*$', body[:pos])):
                endpos = strm.end(0)

        elif poi == 'class':
            klass = reCls.match(body, pos).group(1)
            sys.stderr.write('class ' + klass + '
')

        elif poi == 'function':
            fname = reFun.match(body, pos)
            if fname.group(1):
                fname = klass + '.' + fname.group(1)
            else:
                lastf = stack[-1]
                lastf['anon'] += 1
                fname = lastf['name'] + '.anon' + str(lastf['anon'])
            sys.stderr.write('function ' + fname + '
')
            stack.append({'name':fname, 'depth':depth, 'anon':0})

            brace = body.find('{', pos) + 1
            line = "
var __start__:int = flash.utils.getTimer();"
            body = body[:brace] + line + body[brace:]
            depth += 1
            endpos = brace + len(line)

        elif poi == '{':
            depth += 1

        elif poi == 'return':
            lastf = stack[-1]
            semicolon = body.find(';', pos) + 1
            if sre.match('returns*;', body[pos:]):
                line = "{ Profiler.profiler.profile('" + lastf['name'] + 
                       "', flash.utils.getTimer() - __start__); return; }"
            else:
                retvar += 1
                line = "{ var __ret" + str(retvar) + "__:* =" + body[pos+6:semicolon] + 
                       "
Profiler.profiler.profile('" + lastf['name'] + 
                       "', flash.utils.getTimer() - __start__); return __ret" + str(retvar) + "__; }"
            body = body[:pos] + line + body[semicolon:]
            endpos = pos + len(line)

        elif poi == '}':
            depth -= 1
            if len(stack) > 0 and stack[-1]['depth'] == depth:
                lastf = stack.pop()
                line = "Profiler.profiler.profile('" + lastf['name'] + 
                    "', flash.utils.getTimer() - __start__);
"
                body = body[:pos] + line + body[pos:]
                endpos += len(line)

        pos = endpos
        match = rePOI.search(body, pos)
    return body

def main():
    if len(sys.argv) >= 2: inf = open(sys.argv[1], 'rU')
    else: inf = sys.stdin
    if len(sys.argv) >= 3: outf = open(sys.argv[2], 'wU')
    else: outf = sys.stdout
    outf.write(addProfilingCalls(inf.read()))
    inf.close()
    outf.close()

if __name__ == "__main__":
    main()

随意使用、分发和修改两者.

Feel free to use, distribute and modify both.

这篇关于Flash/Actionscript CPU 分析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆