【问题标题】:Flash / Actionscript CPU profilerFlash / Actionscript CPU 分析器
【发布时间】:2010-09-26 08:21:55
【问题描述】:

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

【问题讨论】:

    标签: flash actionscript profiling cpu-usage


    【解决方案1】:

    Adobe 最近发布了一种新的 Flash 分析工具,称为 Adob​​e Scout:

    http://gaming.adobe.com/technologies/scout/

    这是对旧 Flash Builder 分析器的巨大改进 - 它为您提供了 CPU 时间的详细细分,包括 ActionScript 执行以及渲染和网络等内部播放器功能。

    它在试用期内是免费的 - 您只需注册一个免费的 Creative Cloud 帐户。之后,将继续提供免费的基本版,完整版作为付费 Creative Cloud 帐户的一部分提供。

    【讨论】:

      【解决方案2】:

      我发现The Miner 非常有用,它对非商业项目是免费的。它具有广泛的功能,但标有“Performance Profiler”的选项卡是最有帮助的。我发现这是找到代码瓶颈的好方法,或者至少知道主要原因是什么(渲染、文本、网络等)。

      我花了一些时间才找到安装说明,但这很简单。在项目中包含 .swc 文件,然后在文档类构造函数中添加 1 行代码。

      this.addChild(new TheMiner(true));
      

      更多信息:http://www.sociodox.com/theminer/support.html

      【讨论】:

        【解决方案3】:

        有一个 FlashPreloaderProfiler: http://jpauclair.net/flashpreloadprofiler

        它是用 actionscript 编写的,不需要在后台运行 java 应用程序,并且具有更多功能,例如 Memory Profiler。

        但我也更喜欢 PBLabsProfiler :)

        【讨论】:

          【解决方案4】:

          这是我个人最喜欢的。 请注意,它是基于 java 和开源的。 http://github.com/bengarney/PBLabsProfiler

          它使用了 flash/flex 编译器的未记录功能。 与 Flash Builder 内置分析器使用的相同。 是的!我已经成功地使用它来优化我的一些 Flash 代码。

          【讨论】:

          • 是的,PushButton Labs Profiler 做得很好!
          【解决方案5】:

          我也在寻找用于 AS 的分析器,但我想要一个可与 FlashDevelop 和 Flex SDK 配合使用的免费软件/开源解决方案。我没有找到。所以我写了一个简单的python脚本和一个更简单的AS类。该脚本本质上采用任何 AS 文件并向每个函数定义添加分析代码(即调用以测量该函数的总运行时间,精度为 1 毫秒 - 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()
          

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

          【讨论】:

          • python 脚本的第 31 行出现错误:UnboundLocalError: local variable 'klass' referenced before assignment
          • 我在函数的开头添加了一行来初始化klass。
          • @DavidHanak 请包含有关如何使用工具的说明,以便新手可以使用它们。谢谢
          【解决方案6】:

          我前段时间写了一个基于flasm的flash profiler(http://snow.prohosting.com/bensch/flasp.html)你需要使用flasm插入profiling asm然后运行程序。

          另一个(也许)更好的方法是使用 David Chang 的分析代码,它根本不需要 flasm。 www.nochump.com/asprof/

          干杯

          【讨论】:

            【解决方案7】:

            我使用 Flex Builder 3 附带的分析器取得了一定的成功。我发现在查找内存泄漏和/或 GC 问题时特别有用。

            由于相关应用程序的异步性质以及 [onEnterFrame] 和其他内部方法的时间量,它在方法时间性能方面对我的用处要小得多,尽管我仍然能够根据输出进行一些优化。

            【讨论】:

              【解决方案8】:

              请务必注意,Flash Player 的实现在每个平台上以及在一定程度上每个浏览器都不同,因此预计会有显着的速度差异。因此,如果您正在开发一个资源密集型应用程序,您应该使用特定于您所针对的每个操作系统的分析工具,例如 OS X 上的Instruments,当然还要测试每个浏览器的性能。

              【讨论】:

                【解决方案9】:

                Flex Builder 3 包含一个performance and memory profiler。我没用过,但看起来很时髦。我不确定它是否可以用于非 Flex 内容,但它肯定只适用于 AS3。

                除此之外,多年来,我发现了一些可行的方法来进行一定级别的分析。在最简单的情况下,您显然可以构建一个 FPS 计并观察它的行为。有关代码繁重的应用程序的更多信息,我所做的一件事是创建一个简单的框架,用于在方法的开头和结尾进行 getTimer() 调用并跟踪累积时间,但我从未使用过任何预制的工具。在实践中,代码繁重工作的瓶颈通常很明显,在这些情况下,我只是将计时器直接放在我要优化的地方。

                当瓶颈出现在渲染中时,首先要尝试以目标 FPS 进行发布,并使用 FPS 计来跟踪实际播放何时低于该值(在目标硬件上)。您可以通过例如调用refreshAfterUpdate 的1ms 超时和监控刷新之间的实际时间来获取有关渲染的更多详细信息。不幸的是,您无法获得比“每次刷新”更精细的信息 - 您无法直接看到光栅化、合成等花费了多少时间。(尽管您通常可以推断出这些事情。例如,您可以启用位图缓存在矢量重的对象上取消光栅化,并观察结果。)

                【讨论】:

                • 该链接指向 Flex Builder 3 功能介绍 -- 这不是当前版本吗?
                • 哇,你是对的 - 你可以看到我不是 FB 用户。为了清楚起见,我将进行编辑,但也许更熟悉 FB 分析器的人可以添加有关来龙去脉的信息。谢谢你的收获!
                猜你喜欢
                • 2011-02-19
                • 2012-03-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-05-01
                • 1970-01-01
                • 2018-02-07
                • 1970-01-01
                相关资源
                最近更新 更多