已经在 facebook 上正常运行多年了,获得了广泛的认可。这儿有个讨论帖 https://ruby-china.org/topics/35515
Rails 项目中 ruby 版本和 gemset 大多可以自动切换,是不是痛点得据情况而定,一般在项目切换不频繁时,ruby 版本不会是痛点。
Docker 的本质是对运行环境进行隔离,主要价值在于可保证各个运行环境的一致性。对于环境不一致导致的问题,其实也可以考虑打造一个 和生产环境高度一致的测试环境,在测试环境中暴露问题。一般由于环境不一致导致的问题,其实不会太频繁。如果导致方案整体不可用的情况, 则可能方案的选择上欠考虑或者开发环境和生产环境差别过大。这其实也可以解决环境不一致带来的潜在问题,当然得根据情况而定。
在开发环境中用 docker,除了环境一致性的优点外,其他的差不多可以视为缺点,带来反向价值。特别是对于像我等菜鸟,在开发时,经常拼错单词,
或者变量名取的不好要改,或者其他纰漏。这些小错在代码自动 reload 时,可以高效的解决。docker 嘛,毕竟多了一层,差不多活生生把动态语言开发搞成了静态语言开发,改一下还要构建一下。是否值得选择,也得看自身情况。
至于用了 docker 是否区分 Rails 的三个模式,我实在想不出两者有什么关联。不用 docker 也不妨碍只用一种模式吧,只要你想。用了 docker,有多个模式也不会有问题。关联何在?
以上是我的个人观点。
很棒,值得一看。 直接点这个链接可进 https://v.qq.com/x/page/p0772tw9fij.html
借@so_zengtao的风,来个完整的
Ubuntu MAC centos 安装 jemalloc
sudo apt-get install libjemalloc-dev
brew install jemalloc
sudo yum install -y jemalloc jemalloc-devel
rbenv
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.5.0
rvm
rvm reinstall 2.5.0 --disable-binary --with-jemalloc
源码安装
./configure --with-jemalloc
make
make install
检查安装是否正确
ruby -r rbconfig -e "puts RbConfig::CONFIG['LIBS']"
# 应该输出: -lpthread -ljemalloc -ldl -lobjc
2.3.6 :021 > ENV['RUBY_VERSION']
=> "ruby-2.3.6"
.3.6 :019 > Benchmark.measure { maxa(1000)}
=> #<Benchmark::Tms:0x00007f8a60a4a780 @label="", @real=2.4335659999924246, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=2.42, @total=2.42>
2.3.6 :020 > Benchmark.measure { maxf(1000)}
=> #<Benchmark::Tms:0x00007f8a60a3be88 @label="", @real=0.5101689999864902, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.5100000000000002, @total=0.5100000000000002>
:001 > ENV['RUBY_VERSION']
=> "ruby-2.5.0"
:022 > Benchmark.measure { maxa(1000)}
=> #<Benchmark::Tms:0x00007fe484845d30 @label="", @real=0.46752000000560656, @cstime=0.0, @cutime=0.0, @stime=0.00017400000000000054, @utime=0.46631599999999995, @total=0.46648999999999996>
:023 > Benchmark.measure { maxf(1000)}
=> #<Benchmark::Tms:0x00007fe48282dc78 @label="", @real=0.6195719999959692, @cstime=0.0, @cutime=0.0, @stime=0.0003689999999999978, @utime=0.6181120000000001, @total=0.6184810000000001>
2.3 和 2.5 的测试,确实也是反过来的,而且差别不小。
我想说的是楼主的假设是不是不够科学? [].max 虽然会返回新对象,但是它的执行成本明显要低于max(a,b)
,执行过程本身就会创建一大波对象 (都放在 ObjectSpace 中的),调用越少消耗越少,虽然栈调用的消耗相对较小。
不能简单地根据调用是否返回新对象来判断其性能吧? @quakewang
这个测试用例中被测试的调用是在 each 中的,不知道虚拟机解释的时候,是否有区别优化?
《Ruby 原理剖析》里面介绍过,each 方法每次迭代都准备一大波对象,执行很多逻辑。而 while 只需要调整 PC 指针的值,性能不在一个量级。具体的细节我得回去翻翻书了。
把第五步how to use
整理成一个脚本,在 Dockerfile 中用 ENTRYPOINT/CMD 触发,再加上一个平滑替换容器的脚本,就完美了。
Z-Score ML 里面做数据特征归一化,数学真是无处不在
command :add do |c|
c.action do |global_options,options,args|
$todo_list.create(args)
end
end
等价于:
command(:add) do |c|
c.action do |global_options,options,args|
$todo_list.create(args)
end
end
command(:add)
会返回一个方法,后面的代码块是这个方法的"参数"。
你 nginx 代理静态资源写的是这个:
location ~*^/app/assets/{
}
有这个路径吗?换下下面这个试试:
location ^~ /assets/{
}
顺便建议在 config/environments/production.rb 加上:
config.serve_static_files = false # 不让后端处理静态资源请求,可以检测你nginx是否真的代理的静态资源
将 精靈旅社
,疯狂假期
, 精灵旅社
, 精靈旅社
在写入 ES 时,先全部转化为简体,只存一份。在查询时将所有的繁体转化为简体,再到 ES 查询,可行?
实际情况复杂,关联对象取出来后,在渲染时还需要执行很多业务逻辑,而且对象关联可能不止一层。用 pluck,可能会有局限而且改造成本高。
技师
这个词用的好
不是基于统计的???楼主能不能大概描述一下核心原理?thx
class T
A = {a: 1, b: 3}
def s
{c: 1, d: 1}
end
end
T::A.object_id
=> 70307759309580
T::A.object_id
=> 70307759309580
t = T.new
=> #<T:0x00007fe39ba59ea8>
t.s.object_id
=> 70307772676380
t.s.object_id
=> 70307766481000
最好用配置文件,实在不行,从内存的角度来看,还是放在常量里好些。
很好的思路。将用户权限、用户自定义配置、核心数据配置、顶层数据 ((支持实时多条件查询)、关联数据本身组合打包,一起生成多层 cache_key,再增加层级间的 touch 机制,可以让这套机制跑起来。之前没有这么做,应该是因为缓存命中率和这一锅粥的复杂度,不过这个方案确实值得尝试。
套娃更多的是提升渲染阶段的性能吧,在当前场景下需要做到很小的粒度才有意义,而且还是得先把数据查询出来,难以跳过 includes 带来的问题。
确实,在准备融入项目时发现隐藏成本不小。特别是随着代码量增长,增加新的字段,新的方法时,特别容易埋下坑。这种功能需要写的尽量简洁,易配置,且只用在局部有性能痛点的地方。
是的,一般读多写少怎么玩都行。乐观锁就是因为无锁,吞吐量大些,单次响应快(可能成功,可能失败)。
有时确实容易造成 bug,我换一个例子:
stringArray.each do |s|
if s == 'someString'.freeze
# do something
end
end
环境永远不是完美的,或者说成本(时间/精力等)永远是有限的。我们需要做的事情,就是在这些限制下作出努力,让成本和收益达到某个平衡点。
过分限制 Ruby 创建新对象会极大提升成本,得不偿失。大多数人建议少创建对象,本意是合理使用 Ruby 的特性,让它避免创建某些没有意义的临时对象。例如下面两段代码:
stringArray = stringArray.map do |s|
s.upcase # 会创建新的对象
end # 创建一个新的数组
stringArray.each do |s|
s.upcase! # 不会创建新的对象
end
这些小细节本身微不足道,但是当这些代码被执行千百次时,它带来的整体收益还是可观的。
感谢@nowherekai的提醒和推荐,已经修改正确了。
用 Ruby 很多时候是追求开发效率和开发体验。当应用对内存很敏感,或者说内存消耗造成了明显的问题,而这个问题又是 Ruby 造成的,那么换一种工具(语言)是可以考虑的选择。
语言本身和使用语言的方式,这两个方面可能都得做出一些努力吧。据说 ActiveRecord 在重构了,会创建更少的对象。
嗯,少创建对象是最重要的。文章本意主要是想介绍一下 GC。
感谢提醒,已经修改了。
关于文章内容,请各路大神们提点建议,帮助这篇文章成为 Ruby GC 的扫盲资料,通过文章能对 GC 有基础的了解。感谢!
如果 http 请求本身会堵塞,那么重启后,此症状还不是会重现吗?
进程/线程数开大,同时超时时间更短?
从部署日志上看,你发送的是 TERM 信号,让进程先全部挂了,然后才重新启动。在进程挂掉到新的进程启动完成的过程中,你的服务肯定会有中断的。给进程发送 USR2 信号,puma 本身是支持平滑重启的,https://github.com/puma/puma/blob/master/docs/signals.md
看了一下你的代码,创建 Websockt 连接去获取数据的操作,是在用户的 http 请求中被动触发的。这里面写
数据和读
数据是打包耦合在一起的。你看能不能换一种实现方式,单独开几个线程来实现写
数据,让这两个过程分开。比如在BvHelper::Daemon.run
方法中先创建几个线程去获取数据,然后才EventMachine.start_server
:
require 'eventmachine'
module EchoServer
def receive_data data
puts data
puts $data
end
end
class Server
def self.run
3.times do |i|
Thread.new do
loop do
$data ||= {}
$data[i] = Time.now.to_i
sleep 1
end
end
end
EventMachine.run {
EventMachine.start_server "127.0.0.1", 8081, EchoServer
}
end
end
Server.run