• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >ruby > 对优化Ruby on Rails性能的一些办法的探究

对优化Ruby on Rails性能的一些办法的探究

作者:goldensun 字体:[增加 减小] 来源:互联网

goldensun 通过本文主要向大家介绍了ruby on rails,ruby on rails教程,ruby on rails安装,ruby on rails下载,ruby on rails指南等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

1.导致你的 Rails 应用变慢无非以下两个原因:

  1. 在不应该将 Ruby and Rails 作为首选的地方使用 Ruby and Rails。(用 Ruby and Rails 做了不擅长做的工作)
  2. 过度的消耗内存导致需要利用大量的时间进行垃圾回收。

Rails 是个令人愉快的框架,而且 Ruby 也是一个简洁而优雅的语言。但是如果它被滥用,那会相当的影响性能。有很多工作并不适合用 Ruby and Rails,你最好使用其它的工具,比如,数据库在大数据处理上优势明显,R 语言特别适合做统计学相关的工作。

内存问题是导致诸多 Ruby 应用变慢的首要原因。Rails 性能优化的 80-20 法则是这样的:80% 的提速是源自于对内存的优化,剩下的 20% 属于其它因素。为什么内存消耗如此重要呢?因为你分配的内存越多,Ruby GC(Ruby 的垃圾回收机制)需要做的工作也就越多。Rails 就已经占用了很大的内存了,而且平均每个应用刚刚启动后都要占用将近 100M 的内存。如果你不注意内存的控制,你的程序内存增长超过 1G 是很有可能的。需要回收这么多的内存,难怪程序执行的大部分时间都被 GC 占用了。

2 我们如何使一个 Rails 应用运行更快?

有三种方法可以让你的应用更快:扩容、缓存和代码优化。

扩容在如今很容易实现。Heroku 基本上就是为你做这个的,而 Hirefire 则让这一过程更加的自动化。其它的托管环境提供了类似的解决方案。总之,可以的话你用它就是了。但是请牢记扩容并不是一颗改善性能的银弹。如果你的应用只需在 5 分钟内响应一个请求,扩容就没有什么用。还有就是用 Heroku + Hirefire 几乎很容易导致你的银行账户透支。我已经见识过 Hirefire 把我一个应用的扩容至 36 个实体,让我为此支付了 $3100。我立马就手动吧实例减容到了 2 个, 并且对代码进行了优化.

Rails 缓存也很容易实施。Rails 4 中的块缓存非常不错。Rails 文档 是有关缓存知识的优秀资料。不过同扩容相比,缓存并不能成为性能问题的终极解决方案。如果你的代码无法理想的运行,那么你将发现自己会把越来越多的资源耗费在缓存上,直到缓存再也不能带来速度的提升。

让你的 Rails 应用更快的唯一可靠的方式就是代码优化。在 Rails 的场景中这就是内存优化。而理所当然的是,如果你接受了我的建议,并且避免把 Rails 用于它的设计能力范围之外,你就会有更少的代码要优化。

2.1 避免内存密集型Rails特性

Rails 一些特性花费很多内存导致额外的垃圾收集。列表如下。

2.1.1 序列化程序

序列化程序是从数据库读取的字符串表现为 Ruby 数据类型的实用方法。

class Smth < ActiveRecord::Base
 serialize :data, JSON
end
Smth.find(...).data
Smth.find(...).data = { ... }
</div>

它要消耗更多的内存去有效的序列化,你自己看:

class Smth < ActiveRecord::Base
 def data
 JSON.parse(read_attribute(:data))
 end
 def data=(value)
 write_attribute(:data, value.to_json)
 end
end
</div>

这将只要 2 倍的内存开销。有些人,包括我自己,看到 Rails 的 JSON 序列化程序内存泄漏,大约每个请求 10% 的数据量。我不明白这背后的原因。我也不知道是否有一个可复制的情况。如果你有经验,或者知道怎么减少内存,请告诉我。

2.1.2 活动记录

很容易与 ActiveRecord 操纵数据。但是 ActiveRecord 本质是包装了你的数据。如果你有 1g 的表数据,ActiveRecord 表示将要花费 2g,在某些情况下更多。是的,90% 的情况,你获得了额外的便利。但是有的时候你并不需要,比如,批量更新可以减少 ActiveRecord 开销。下面的代码,即不会实例化任何模型,也不会运行验证和回调。

Book.where('title LIKE ?', '%Rails%').update_all(author: 'David')
后面的场景它只是执行 SQL 更新语句。

update books
 set author = 'David'
 where title LIKE '%Rails%'
Another example is iteration over a large dataset. Sometimes you need only the data. No typecasting, no updates. This snippet just runs the query and avoids ActiveRecord altogether:
result = ActiveRecord::Base.execute 'select * from books'
result.each do |row|
 # do something with row.values_at('col1', 'col2')
end
</div>

2.1.3 字符串回调

Rails 回调像之前/之后的保存,之前/之后的动作,以及大量的使用。但是你写的这种方式可能影响你的性能。这里有 3 种方式你可以写,比如:在保存之前回调:

before_save :update_status
before_save do |model|
model.update_status
end
before_save “self.update_status”

</div>

前两种方式能够很好的运行,但是第三种不可以。为什么呢?因为执行 Rails 回调需要存储执行上下文(变量,常量,全局实例等等)就是在回调的时候。如果你的应用很大,你最终在内存里复制了大量的数据。因为回调在任何时候都可以执行,内存在你程序结束之前不可以回收。

有象征,回调在每个请求为我节省了 0.6 秒。

2.2 写更少的 Ruby

这是我最喜欢的一步。我的大学计算机科学类教授喜欢说,最好的代码是不存在的。有时候做好手头的任务需要其它的工具。最常用的是数据库。为什么呢?因为 Ruby 不善于处理大数据集。非常非常的糟糕。记住,Ruby 占用非常大的内存。所以举个例子,处理 1G 的数据你可能需要 3G 的或者更多的内存。它将要花费几十秒的时间去垃圾回收这 3G。好的数据库可以一秒处理这些数据。让我来举一些例子。

2.2.1 属性预加载

有时候反规范化模型的属性从另外一个数据库获取。比如,想象我们正在构建一个 TODO 列表,包括任务。每个任务可以有一个或者几个标签标记。规范化数据模型是这样的:

  • Tasks
  •  id
  •  name
  • Tags
  •  id
  •  name
  • Tasks_Tags
  •  tag_id
  •  task_id

加载任务以及它们的 Rails 标签,你会这样做:

这段代码有问题,它为每个标签创建了对象,花费很多内存。可选择的解决方案,将标签在数据库预加载。

tasks = Task.select <<-END
  *,
  array(
  select tags.name from tags inner join tasks_tags on (tags.id = tasks_tags.tag_id)
  where tasks_tags.task_id=tasks.id
  ) as tag_names
 END
 > 0.018 sec
</div>

这只需要内存存储额外一列,有一个数组标签。难怪快 3 倍。

2.2.2 数据集合

我所说的数据集合任何代码去总结或者分析数据。这些操作可以简单的总结,或者一些更复杂的。以小组排名为例。假设我们有一个员工,部门,工资的数据集,我们要计算员工的工资在一个部门的排名。

SELECT * FROM empsalary;
</div>
 depname | empno | salary
-----------+-------+-------
 develop |  6 | 6000
 develop |  7 | 4500
 develop |  5 | 4200
 personnel |  2 | 3900
 personnel |  4 | 3500
 sales  |  1 | 5000
 sales  |  3 | 4800
</div>

你可以用 Ruby 计算排名:

salaries = Empsalary.all
salaries.sort_by! { |s| [s.depname, s.salary] }
key, counter = nil, nil
salaries.each do |s|
 if s.depname != key
 key, counter = s.depname, 0
 end
 counter += 1
 s.rank = counter
end
</div>

Empsalary 表里 100K 的数据程序在 4.02 秒内完成。替代 Postgres 查询,使用 window 函数做同样的工作在 1.1 秒内超过 4 倍。

SELECT depname, empno, salary, rank()
OVER (PARTITION BY depname ORDER BY salary DESC)
FROM empsalary;
</div>
 depname | empno | salary | rank 
-----------+-------+--------+------
 develop |  6 | 6000 | 1
 develop |  7 | 4500 | 2
 develop |  5 | 4200 | 3
 personnel |  2 | 3900 | 1
 personnel |  4 | 3500 | 2
 sales  |  1 | 5000 | 1
 sales  |  3 | 4800 | 2
</div>

4 倍加速已经令人印象深刻,有时候你得到更多,到 20 倍。从我自己经验举个例子。我有一个三维 OLAP 多维数据集与 600k 数据行。我的程序做了切片和聚合。在 Ruby 中,它花费了 1G 的内存大约 90 秒完成。等价的 SQL 查询在 5 内完成。

2.3 优化 Unicorn

如果你正在使用Unicorn,那么以下的优化技巧将会适用。Unicorn 是 Rails 框架中最快的 web 服务器。但是你仍然可以让它更运行得快一点。

2.3.1 预载入 App 应用

Unicorn 可以在创建新的 worker 进程前,预载入 Rails 应用。这样有两个好处。第一,主线程可以

您可能想查找下面的文章:

  • Rails bundle命令安装mysql gem包出错的解决方法
  • win7安装ruby on rails开发环境
  • 简单对比分析Ruby on Rails 和 Laravel
  • 在 Ubuntu 12.04 Server 上安装部署 Ruby on Rails 应用
  • 快速正确的安装 Ruby, Rails 运行环境
  • Windows下Ruby on Rails开发环境安装配置图文教程
  • Ruby On Rails中如何避免N+1问题
  • 艰难完成 nginx + puma 部署 rails 4的详细记录
  • 浅谈Rails 4 中Strong Parameters机制
  • Rails命令行常用操作命令简明总结

相关文章

  • CentOS 6.3下编译安装Ruby 2.0笔记
  • Ruby 多线程的潜力和弱点分析
  • Ruby实现的一个强大的批量删除文件脚本分享
  • Ruby on Rails中的ActiveRecord编程指南
  • 详细解析Ruby中的变量
  • Ruby中变量引用时的一些注意点
  • 简单介绍Ruby on Rails对PostgreSQL数组类型的支持
  • Ubuntu上配置Ruby on Rails框架及RubyMine IDE开发环境
  • Ruby教程之注释、变量声明以及数组操作
  • Ruby中case表达式详解

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • 在Ruby中创建和使用哈希的教程
    • Ruby on Rails迁移时的一些注意事项
    • 在Ruby on Rails上使用Redis Store的方法
    • ruby实现修改ubuntu下的hosts
    • rails创建应用程序实例
    • 在 Ubuntu 12.04 Server 上安装部署 Ruby on Rails 应用
    • RVM安装和使用总结笔记
    • PHP实现的一个保存远程文件到本地的函数分享
    • 在Ruby on Rails中使用Markdown的方法
    • ruby 异常处理:ensure

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有