帮酷LOGO
  • 显示原文与译文双语对照的内容
文章标签:rails  benchmarks  faster  benchmark  fast  
Go faster, off the Rails - Benchmarks for your whole Rails app

  • 源代码名称:derailed_benchmarks
  • 源代码网址:http://www.github.com/schneems/derailed_benchmarks
  • derailed_benchmarks源代码文档
  • derailed_benchmarks源代码下载
  • Git URL:
    git://www.github.com/schneems/derailed_benchmarks.git
  • Git Clone代码到本地:
    git clone http://www.github.com/schneems/derailed_benchmarks
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/schneems/derailed_benchmarks
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
  • 中断的基准测试

    一系列可以用来测试 Rails 或者 ruby 应用程序的东西。

    Build StatusHelp Contribute to Open Source

    的兼容性/需求

    这个 gem 已经测试过,可以使用 ruby 2.1 + 来处理 Rails 3.2 + 。 一些命令可以在旧版本的ruby 上工作,但不能支持所有命令。

    对于一些基准而言,不是全部,你需要验证你的操作系统上的curl的工作版本:

    $ which curl
    /usr/bin/curl
    $ curl -V
    curl 7.37.1 #...

    安装

    把这个放在你的邮箱里:

    gem 'derailed_benchmarks', group::development

    然后运行 $ bundle install

    在执行命令时,你可能需要在键入命令之前使用 bundle exec

    若要使用所有可用的分析方法,还可以添加:

    gem 'stackprof', group::development

    你必须使用 ruby 2.1 + 来安装这些库。 如果你是 ruby的老版本,你在等待什么?

    使用

    有两种方法可以对应用程序进行基准测试。 about可以以尝试引导web应用程序,并在基准测试时对它运行请求。 引导你的应用程序总是更准确,但如果你无法在生产中运行你的应用程序,你仍然会找到 static 信息。

    static-基准测试

    本节介绍如何从你的Gemfile获取内存信息,而不必引导你的应用程序。

    本节中的所有命令都将以 $ derailed bundle: 开头

    有关内存与性能之间关系的详细信息,请阅读/观看如何使用内存。

    在需要时使用的内存

    你添加到项目中的每个 gem 都可以提高你在启动时的内存。 运行时,可以在你的Gemfile中查看每个 gem 使用的总内存:

    $ bundle exec derailed bundle:mem

    这将加载你的Gems 中的每个,并查看它们在需要时消耗了多少内存。 例如如果你正在使用 mail gem 。 输出可能如下所示

    $ bundle exec derailed bundle:mem
    TOP: 54.1836 MiB
     mail: 18.9688 MiB
     mime/types: 17.4453 MiB
     mail/field: 0.4023 MiB
     mail/message: 0.3906 MiB
     action_view/view_paths: 0.4453 MiB
     action_view/base: 0.4336 MiB

    :"mib"是 /的/符号,是1 字节/1024 Kibibytes ( 依次为 1024字节) 。

    在这里我们可以看到 mail 使用了 18个 MiB,大多数来自 mime/types 。 你可以使用这里信息来删除你不需要的大型依赖项。 如果你看到需要的gem的大内存使用,请打开该库的问题,让它们知道( 请确保包含复制指令) 。 希望作为一个社区,我们可以识别内存热点并减少它们的影响。 在修复性能问题之前,我们需要知道这些问题存在的位置。

    默认情况下,这里任务将只返回 :default"production" 组的结果。 如果你想使用不同的组,可以使用。

    $ bundle exec derailed bundle:mem development

    你可以以使用 CUT_OFF=0.3 只显示具有特定内存使用情况的文件,这可以以帮助消除噪音。

    注意:这里方法不会在你自己的应用程序中包含文件,只有你的应用程序中的项目。 因为你需要使用 bundle exec derailed exec mem 有关详细信息,请参阅下面的。

    由于 ruby 只需要一次文件,因这里成本只与第一个库相关联,需要一个文件。 为了使这个更可见的重复条目,重复条目将列出他们所有的父母。 例如 mailfog 都需要 `mime/类型。 因此它可能会在你的应用程序中显示类似的内容:

    $ bundle exec derailed bundle:mem
    TOP: 54.1836 MiB
     mail: 18.9688 MiB
     mime/types: 17.4453 MiB (Also required by: fog/storage)
     mail/field: 0.4023 MiB
     mail/message: 0.3906 MiB

    这样你就会知道仅删除顶级库( 邮件) 将不会导致内存减少。 输出在前两个条目后被截断:

    fog/core: 0.9844 MiB (Also required by: fog/xml, fog/json, and 48 others)
    fog/rackspace: 0.957 MiB
    fog/joyent: 0.7227 MiB
     fog/joyent/compute: 0.7227 MiB

    如果你想看到所有需要 fog/core的东西,你可以运行 CUT_OFF=0 bundle exec derailed bundle:mem 获取完整的输出,然后手动通过手动。

    更新:虽然 mime/types 在这些示例中看起来很糟糕,但是它已经被修复。 你可以将它添加到你的gemfile的顶部以获取可用内存:

    gem 'mime-types', [ '~> 2.6', '>= 2.6.1' ], require:'mime/types/columnar'

    在需要时创建的对象

    要获取有关对象的更多信息,请使用 memory_profiler插件,在依赖项要求你运行时创建:

    $ bundle exec derailed bundle:objects

    这将输出在加载依赖项时创建的对象的详细信息

    Measuring objects created by gems in groups [:default,"production"]
    Total allocated 433895
    Total retained 100556
    allocated memory by gem
    -----------------------------------
     24369241 activesupport-4.2.1
     15560550 mime-types-2.4.3
     8103432 json-1.8.2

    一旦标识了创建大量内存的gem,使用 $ bundle exec derailed bundle:mem 你可以把那个 gem 放到它自己的文件里 $ bundle exec derailed bundle:objects 获取有关它的详细信息。 这些信息可以由贡献者和库作者用来识别和消除对象创建热点。

    默认情况下,这里任务将只返回 :default"production" 组的结果。 如果你想使用不同的组,可以使用。

    $ bundle exec derailed bundle:objects development

    注意:这里方法不会在你自己的应用程序中包含文件,只有你的应用程序中的项目。 因为你需要使用 bundle exec derailed exec objects 有关详细信息,请参阅下面的。

    基于的动态应用

    这个基准测试将尝试启动你的Rails 应用程序并针对它。 static 基准测试不同 $ bundle exec derailed bundle:* 这些将包括有关你的特定应用程序的信息。 专业的是你会获得更多的信息和潜在的发现问题,在你的应用程序代码,它要求你能够引导和运行在本地的应用程序,这是一些应用程序不是很简单的。

    你可能需要查看迷你分析器,这是一个迷你探查器演练。 它比你在这里发现的要好并且有点不同。

    正在本地运行。

    在试图尝试任何动态基准之前,需要在 production 模式下引导应用程序。 因为它接近你的部署性能,所以我们使用 production 。 本节是一些提示的集合,而不是实际教程。

    对于初学者,尝试启动到控制台:

    $ RAILS_ENV=production rails console

    如果你不能够连接到 production 数据库,可能会出现错误。 为此,可以使用生产数据库的NAME 创建本地数据库,也可以将 development 组中的信息复制到 database.yml 中的production 组。

    你可能在 production 中缺少 环境变量,如 SECRET_KEY_BASE 。 对于那些你可以把它们提交到你的.env 文件( 如果你使用的是) 。 或者直接将它们添加到命令中:

    $ SECRET_KEY_BASE=foo RAILS_ENV=production rails console

    在生产中启动控制台后,你需要能够在生产环境中引导服务器

    $ RAILS_ENV=production rails server

    你可能需要暂时禁用强制SSL或者其他域限制。 如果这样做,请不要忘记在部署任何代码( eek ) 之前将它们添加回去。

    如果你使用 rails_12factor gem,或者通过运行 log/production.log,则可以从获得信息

    $ tail -f log/production.log

    修复所有错误并在生产中运行服务器后,几乎就可以。

    正在运行脱轨执行

    你可以运行 $ derailed exec 来针对你的应用程序运行命令。 下面是设置 rack 和使用经过身份验证的请求的部分。 你可以通过运行以下命令查看哪些命令可用:

    $ bundle exec derailed exec --help
     $ derailed exec perf:allocated_objects # outputs allocated object diff after app is called TEST_COUNT times
     $ derailed exec perf:gc # outputs GC::Profiler.report data while app is called TEST_COUNT times
     $ derailed exec perf:ips # iterations per second
     $ derailed exec perf:mem # show memory usage caused by invoking require per gem
     $ derailed exec perf:objects # profiles ruby allocation
     $ derailed exec perf:mem_over_time # outputs memory usage over time
     $ derailed exec perf:test # hits the url TEST_COUNT times

    我们将查看常见的问题,而不是检查常见的问题,哪些命令最好用于诊断它们。 稍后我们将介绍你可以用来配置脱轨基准的所有 环境变量 。

    是我的应用程序泄漏内存?

    如果你的应用程序泄漏了大量内存,你将首先验证它是否是实际未绑定的"泄漏"。 内存泄漏会永久增加内存使用,多数应用程序会增加内存使用,直到它们按下某个内存。 要诊断这里问题,你可以运行:

    $ bundle exec derailed exec perf:mem_over_time

    这将引导你的应用程序,并用请求命中它并将内存输出到 stdout ( 。/tmp下的文件) 。 它可能类似于:

    $ bundle exec derailed exec perf:mem_over_time
    Booting: production
    Endpoint:"/"
    PID: 78675
    103.55078125
    178.45703125
    179.140625
    180.3671875
    182.1875
    182.55859375
    #.. .
    183.65234375
    183.26171875
    183.62109375

    在这里我们可以看到,内存使用量增加,它的级别约为 183个。 你将希望使用不断增加的TEST_COUNT= 值来运行这里任务,例如

    $ TEST_COUNT=5000 bundle exec derailed exec perf:mem_over_time
    $ TEST_COUNT=10_000 bundle exec derailed exec perf:mem_over_time
    $ TEST_COUNT=20_000 bundle exec derailed exec perf:mem_over_time

    适当调整你的计数,以便在合理的时间内得到结果。 如果你的记忆没有水平,恭喜 ! 你的记忆泄露了 ! 我建议从生成的Google Docs 文件中复制和粘贴值,并绘制图形以便能够更好地理解行的斜率。

    如果不希望它生成带有 SKIP_FILE_WRITE=1 运行结果的tmp文件。

    如果你非常确信存在内存泄漏,但是你不能使用这里方法确认。 看看下面的环境变量选项,你可以尝试点击不同的端点等。

    剖析内存泄漏

    如果你确定了内存泄漏,或者者你只想看到你的内存使用来自哪里,你将希望使用

    $ bundle exec derailed exec perf:objects

    这里任务将按你的应用程序,并使用memory_profiler查看对象的创建位置。 你可能希望运行一次,然后用较高的TEST_COUNT 运行它,这样你就可以看到在每一个请求中创建对象的热点,而只需要在第一个。

    $ TEST_COUNT=10 bundle exec derailed exec perf:objects

    这是一个昂贵的操作,所以你可以能想要保持计数 lowish 。 确定热点读取如何使用内存内存关于减少对象分配的一些提示。

    这类似于 $ bundle exec derailed bundle:objects 它包含在运行时创建的对象。 它对于实际的生产性能调试更加有用,另一种更适合于库作者进行调试。

    我想要堆转储

    如果你仍然挣扎运行时内存,你可以生成一个堆转储,以后可以使用 heap_inspect进行分析。

    $ bundle exec derailed exec perf:heap
    Booting: production
    Heap file generated:"tmp/2015-10-01T12:31:03-05:00-heap.dump"
    Analyzing Heap
    ==============
    Generation: 0 object count: 209307
    Generation: 35 object count: 31236
    Generation: 36 object count: 36705
    Generation: 37 object count: 1301
    Generation: 38 object count: 8
    Try uploading"tmp/2015-10-01T12:31:03-05:00-heap.dump" to http://tenderlove.github.io/heap-analyzer/

    有关从堆转储获取数据的更多帮助,请参见

    $ heapy --help

    在引导时,的内存非常大。

    ruby 内存通常向一个方向,向上。 如果在引导应用程序时内存很大,它可能只会增加。 除了在运行 $ derailed bundle:mem的依赖项中调试内存时,你可以能希望看到自己的文件是如何有效的。

    这里任务实际上是同样的事情,但它按一个请求来确保最后一分钟 require -s被调用。 要执行,可以运行:

    $ bundle exec derailed exec perf:mem
    TOP: 54.1836 MiB
     mail: 18.9688 MiB
     mime/types: 17.4453 MiB
     mail/field: 0.4023 MiB
     mail/message: 0.3906 MiB
     action_view/view_paths: 0.4453 MiB
     action_view/base: 0.4336 MiB

    你可以以使用 CUT_OFF=0.3 只显示具有特定内存用途的文件,这可以以帮助消除噪音。

    如果你的应用程序代码在引导时是exremely大,请考虑使用 $ derailed exec perf:objects 调试低级别对象创建。

    我的应用程序太慢了

    嗯。"。"。不是全部。如果你已经经考虑减少对象分配,你将看到应用程序的代码。 一旦你知道了,你就会知道在哪里可以优化时间。

    一种技术是使用"采样"堆栈分析器。 这种分析类型查看在给定时间间隔执行的方法并记录它。 在执行结束时,它计算调用给定方法的所有时间,并显示每种方法所花费的时间百分比。 这是一种非常低开销的方法来查看执行。 ruby 2.1 + 在 gem 表单中具有这种可用性,它称为 stackprof 。 就像你猜测的那样,可以用脱轨的基准来运行它,首先将它添加到你的gemfile gem"stackprof", group: :development 然后执行:

    $ bundle exec derailed exec perf:stackprof
    ==================================
     Mode: cpu(1000)
     Samples: 16067 (1.07% miss rate)
     GC: 2651 (16.50%)
    ==================================
     TOTAL (pct) SAMPLES (pct) FRAME
     1293 (8.0%) 1293 (8.0%) block in ActionDispatch::Journey::Formatter#missing_keys
     872 (5.4%) 872 (5.4%) block in ActiveSupport::Inflector#apply_inflections
     935 (5.8%) 802 (5.0%) ActiveSupport::SafeBuffer#safe_concat
     688 (4.3%) 688 (4.3%) Temple::Utils#escape_html
     578 (3.6%) 578 (3.6%) ActiveRecord::Attribute#initialize
     3541 (22.0%) 401 (2.5%) ActionDispatch::Routing::RouteSet#url_for
     346 (2.2%) 346 (2.2%) ActiveSupport::SafeBuffer#initialize
     298 (1.9%) 298 (1.9%) ThreadSafe::NonConcurrentCacheBackend#[]
     227 (1.4%) 227 (1.4%) block in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#exec_no_cache
     218 (1.4%) 218 (1.4%) NewRelic::Agent::Instrumentation::Event#initialize
     1102 (6.9%) 213 (1.3%) ActiveSupport::Inflector#apply_inflections
     193 (1.2%) 193 (1.2%) ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper#deprecate_string_options
     173 (1.1%) 173 (1.1%) ActiveSupport::SafeBuffer#html_safe?
     308 (1.9%) 171 (1.1%) NewRelic::Agent::Instrumentation::ActionViewSubscriber::RenderEvent#metric_name
     159 (1.0%) 159 (1.0%) block in ActiveRecord::Result#hash_rows
     358 (2.2%) 153 (1.0%) ActionDispatch::Routing::RouteSet::Generator#initialize
     153 (1.0%) 153 (1.0%) ActiveRecord::Type::String#cast_value
     192 (1.2%) 143 (0.9%) ActionController::UrlFor#url_options
     808 (5.0%) 127 (0.8%) ActiveRecord::LazyAttributeHash#[]
     121 (0.8%) 121 (0.8%) PG::Result#values
     120 (0.7%) 120 (0.7%) ActionDispatch::Journey::Router::Utils::UriEncoder#escape
     2478 (15.4%) 117 (0.7%) ActionDispatch::Journey::Formatter#generate
     115 (0.7%) 115 (0.7%) NewRelic::Agent::Instrumentation::EventedSubscriber#event_stack
     114 (0.7%) 114 (0.7%) ActiveRecord::Core#init_internals
     263 (1.6%) 110 (0.7%) ActiveRecord::Type::Value#type_cast
     8520 (53.0%) 102 (0.6%) ActionView::CompiledTemplates#_app_views_repos__repo_html_slim__2939326833298152184_70365772737940

    从这里你可以深入到各个方法。

    这种性能变化更快?

    微型基准可以能会告诉你代码级别有多快,但是整个应用程序的速度是多少。 如果你想知道性能更改对应用程序的有效性,将它与现有应用程序性能比较很有用。 要帮助你,你可以使用:

    $ bundle exec derailed exec perf:ips
    Endpoint:"/"
    Calculating -------------------------------------
     ips 1.000 i/100ms
    -------------------------------------------------
     ips 3.306 (± 0.0%) i/s - 17.000

    这将在你的应用程序中使用基准 ips ( 。 在"每秒迭代次数"中,更高的值总是更好。 你可以使用这个方法多次运行代码,然后运行"基准线"代码库( 没有你的改变) 来查看它如何影响你的总体性能。 你将需要多次运行并记录结果,这样你就可以消除噪音。 基准测试很难,这种技术并不完美,但是它确实比没有好。

    如果你注意到你也可以运行纯基准( 没有 ips ):

    $ bundle exec derailed exec perf:test

    但我不认为基准ip是个更好的方法。

    环境变量

    所有任务都以 环境变量的形式接受配置。

    增加或者减少测试计数 TEST_COUNT

    对于运行多次的任务,你可以使用 TEST_COUNT 来设置数字,例如:

    $ TEST_COUNT=100_000 bundle exec derailed exec perf:test

    使用 PATH_TO_HIT 命中另一个端点

    默认情况下,任务将按你的主页 / 。 如果要点击不同的url,例如如果你想转到,你可以执行以下命令:

    $ PATH_TO_HIT=/users/new bundle exec derailed exec perf:mem

    这里方法接受完整的uri 。 例如允许你命中子域端点:

    $ PATH_TO_HIT=http://subdomain.lvh.me:3000/users/new bundle exec derailed exec perf:mem

    注意,不能将完整的uri与 USE_SERVER 组合在一起。

    设置HTTP头

    你可以通过设置 HTTP_<header name> 变量来指定HTTP头。 例如:

    $ HTTP_AUTHORIZATION="Basic YWRtaW46c2VjcmV0n" 
     HTTP_USER_AGENT="Mozilla/5.0" 
     PATH_TO_HIT=/foo_secret bundle exec derailed exec perf:ips

    使用带有 USE_SERVER的真正网络服务器

    如果你想使用web服务器将 USE_SERVER 设置为符合 Rack::Server的服务器,则所有测试都不使用web服务器( 默认情况下直接使用 Rack::Mock ),如 webrick

    $ USE_SERVER=webrick bundle exec derailed exec perf:mem

    或者

    $ USE_SERVER=puma bundle exec derailed exec perf:mem

    这个引导服务器使用 curl 而不是内存来访问它。 如果你认为性能问题与你的服务器有关,那么这很有用。

    注意:这个插件直接插入到 rack 中,它不使用你设置的任何 puma.config 文件 等等 。 如果你想这样做,我将开启关于如何( 和拉请求)的建议。

    排除 ActiveRecord

    在默认情况下,如果 gem 作为依赖项包含,则脱轨将加载 ActiveRecord 。 如果你只包含 rails gem,则默认情况下包括。 如果使用不同的ORM,你可能只需要包含 railties gem,或者设置 DERAILED_SKIP_ACTIVE_RECORD 标志。

    $ DERAILED_SKIP_ACTIVE_RECORD=true

    在不同的环境中运行

    默认情况下,测试在生产环境中运行,但是如果你的应用程序没有在本地运行 RAILS_ENV 设置为 production,那么很容易。 例如:

    $ RAILS_ENV=development bundle exec derailed exec perf:mem

    perf.rake

    如果你想自定义失败,你需要在你试图基准测试的目录的root 中创建一个 perf.rake 文件。

    使用rake直接运行基准测试是可能

    $ cat <<EOF> perf.rake
     require 'bundler'
     Bundler.setup
     require 'derailed_benchmarks'
     require 'derailed_benchmarks/tasks'
    EOF

    文件应如下所示:

    $ cat perf.rake
     require 'bundler'
     Bundler.setup
     require 'derailed_benchmarks'
     require 'derailed_benchmarks/tasks'

    这样做是为了在应用程序之前加载基准测试,这对于一些基准测试来说很重要,而对于其他。 这样也防止在不需要这些基准时意外加载这些基准。

    然后你可以通过rake执行命令。

    要找出可用的任务,可以使用 $ rake -f perf.rake -T 基本上说,使用 perf.rake 文件并列出所有任务。

    $ rake -f perf.rake -T

    rack-设置

    使用 Rails你不需要做任何特殊的事情。 如果你正在使用 rack,你需要告诉我们如何引导你的应用程序。 在 perf.rake 文件中添加任务:

    namespace :perfdo task :rack_loaddoDERAILED_APP=# your code hereendend

    将常量 DERAILED_APP 设置为 rack 应用程序。 有关详细信息,请参阅 schneems/derailed_benchmarks#1

    设置这里设置的示例如下所示:

    # perf.rakerequire'bundler'Bundler.setuprequire'derailed_benchmarks'require'derailed_benchmarks/tasks'namespace :perfdo task :rack_loaddorequire_relative'lib/application'DERAILED_APP=MyApplication::Routesendend

    身份验证

    如果试图测试具有身份验证的终结点,则需要告诉任务如何绕过该身份验证。 身份验证由 DerailedBenchmarks.auth 对象控制。 有一个内置的支持设计。 如果使用其他身份验证方法,则可以编写自己的身份验证策略。

    要在测试运行中启用身份验证,请执行以下操作:

    $ USE_AUTH=true bundle exec derailed exec perf:mem

    请参见下面的如何自定义身份验证。

    带设计的身份验证

    如果你使用的是设计,那么有一个内置的身份验证 helper 来检测设计 gem 和自动加载的存在。

    在 root 中创建 perf.rake 文件。

    $ cat perf.rake

    如果你希望你可以自定义,则可以在 perf.rake 文件中设置该值来自定义登录的用户。

    DerailedBenchmarks.auth.user =-> { User.find_or_create!(twitter:"schneems") }

    你需要提供有效的用户,因这里根据你在 user.rb 中的验证,你可以能需要提供不同的参数。

    如果试图验证非用户模型,则需要编写自己的自定义身份验证策略。

    自定义身份验证策略

    要实现你自己的认证策略,你需要创建一个类,从 auth_helper.rb 继承。 你将需要实现 setupcall 方法。 你可以看到的一个示例,即如何编写 devise helper 。 你可以将这里代码放入 perf.rake 文件中。

    classMyCustomAuth <DerailedBenchmarks::AuthHelperdefsetup# initialize code hereenddefcall(env)
     # log something in on each request app.call(env)
     endend

    设计策略通过在 rack 请求内启用测试模式并插入存根用户来实现。 你将需要复制该逻辑,以便你自己的身份验证方案,如果你没有使用设计。

    有了类之后,就需要将 DerailedBenchmarks.auth 设置为类的新实例。 在 perf.rake 文件中添加:

    DerailedBenchmarks.auth =MyCustomAuth.new

    现在,在 USE_AUTH 环境变量设置的每个请求上,将调用 MyCustomAuth#call 方法。

    许可证

    MIT

    确认

    大多数命令都是其他库的包装器,请查看它们。 同时感谢 @tenderlove,我在他的一个项目中从一个项目中获得一些 Rails init代码。

    kthksbye @schneems



    文章标签:fast  rails  benchmark  faster  benchmarks  

    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语