你有没有找到这样一个工具并成功使用它?
解决方法
我也在寻找AS的分析器,但是我想要一个可以与FlashDevelop和Flex SDK一起使用的免费软件/开源解决方案。我没有找到。所以我写了一个简单的python脚本和一个更简单的AS类。该脚本基本上采用任何AS文件,并添加了分析代码(即调用以测量该功能的总运行时间,精度为1 ms,即flash.utils.getTimer()调用的分辨率)到每个函数定义。脚本有时候会出错,但这些脚本通常很容易用手修复。然后,您需要手动添加一行:在某一时刻将分析统计信息转储到某处。这种方法显然远不是准确的,但是它给你的代码带来了瓶颈的良好感觉。我用它成功的一个100k文件。
这是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 + ":\t" + data[fn] + "\n"; } return st; } } }
这里是python脚本的诀窍:
import sre,sys rePOI = sre.compile(r'''\bclass\b|\bfunction\b|\breturn\b|["'/{}]''') reFun = sre.compile(r'\bfunction\b\s*((?:[gs]et\s+)?\w*)\s*\(') reCls = sre.compile(r'class\s+(\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 + '\n') 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 + '\n') stack.append({'name':fname,'depth':depth,'anon':0}) brace = body.find('{',pos) + 1 line = "\nvar __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('return\s*;',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] + \ "\nProfiler.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__);\n" 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()
随意使用,分发和修改两者。