Move To Multi-threaded Rails
July 17th, 2009
When doing performance in local box, we found that requests are waiting to be processed due to Rails is single-threaded by default. We changed the configuration to enable multi-threaded mode as described in this blog entry:
(also refer to Rails 2.2 release notes )
The most important change was to eager-load /lib directory, and thus move libraries for test out of it.
config.threadsafe! also disables automatic loading by ActiveSupport::Dependencies. Alternatively, you can just add lib/ directory to eager load paths. The following inside production.rb will do that :
config.eager_load_paths << "#{RAILS_ROOT}/lib"
We had some rough tests to ensure the functionality is not broken. Multi-threaded mode also might require more memory than single-threaded mode. Still keep testing.
Hack Rails的事务机制
October 19th, 2008
- ActiveRecord不支持嵌套事务。
- 为了简单我们在ApplicationController里做了个filter,于是所有POST/PUT/DELETE的action都被包裹在一个事务里,事务边界是整个请求。
- 偏偏有时候你希望让某个操作中的某个部分不被包含在事务里。原因是当某些操作同时进行,你想看到的不是原子的结果,而是所有同时进行的操作汇总的最终结果
- 比如说,“审核改进措施”这个操作中包含了“重新算分”。
- 某企业有两项改进措施R1和R2,分别对应考核类别C1和C2。C1的原始分数是98,C2的原始分数是89。
- R1能给C1加回1分,R2能给C2加回11分。也就是说审核R1之后C1变成99分,审核R2后C2变成100分。
- 但,“重新算分”是在整个“审核”的事务之中的,于是如果R1和R2同时审核,你一定会看到下列两种原子结果之一:
- C1 99分,C2 89分;或者
- C1 98分,C2 100分。
- 其实这个时候我们不想让“重新算分”跟“审核”成为原子操作,我们希望把“算分”从“审核”的事务里拿出来,这样最后一次算分一定能体现最终的分数状态。
- 可以开一个 线程 或者进程(比如 Kernel.system )把算分的逻辑分出来。
- 因为可以确定“算分”不会跟“审核”发生死锁,所以把这个线程join起来。
- 一定要小心,要是算分跟审核修改到同一条数据那么就会死锁…因为审核等待算分线程结束,而算分线程等待审核交出数据锁。
- 多个算分线程之间是不会死锁滴…为了确保时序可以一上来就锁自己最后要更新的分数记录。
昨天的AJAX就是今天的并发编程
August 5th, 2008
(From The Productive Programmer )
顶多就在五年前,我们炮制的那些丑陋得简直就像把命令行窗口直接塞进浏览器的web应用还能让用户满意。可是Google那些讨厌的程序员毁了这一切:他们发布了Google Maps和Gmail,更要紧的是他们让用户明白web应用不一定要那么糟烂的,于是我们只好跟着开发更好的web应用。现在并发编程的情况也是一样:我们这些程序员现在还可以幸福地对严重的线程问题视而不见,但一定会有人站出来,让人们看到某种新发明的威力,然后我们又得亦步亦趋地跟上去。我们的计算机有强大的运算能力,而我们却没有能力写出那样的代码来充分利用它们,这对矛盾正在日益凸显。
从Py2Erl开始的半天搜索
October 24th, 2007
(昨天发在ECUG的一个邮件,想了一下,还是放到自己blog上)
今天上午,尝试用ErlyWeb做一个petstore,最终被击败了。CaoYuan的blog帮了很大忙:
http://blogtrader.net/page/dcaoyuan/entry/from_rails_to_erlyweb_part2
结论:ErlyWeb在开发便利性方面距离Rails不是一点半点。尤其是view可用的工具太少,有太多东西要从头做起。用来做web前端,不仅有高射炮打蚊
中午写InfoQ的这个报道,其间看了一遍"Py2Erl"那个讲稿,兴趣起来了。
InfoQ报道:http://www.infoq.com/cn/news/2007/10/cn-erlounge-ii
讲稿:http://www.erlang.org.cn/ecug/071013-erlparty2/071014-py2erl/
找到了Stackless Python,写了一段小程序。好玩,靠谱。
Stackless Python:http://www.stackless.com/
抄一段小程序:http://gigix.thoughtworkers.org/2007/10/23/is-stackless-python-the-way
有人做了benchmark,差强人意吧
http://muharem.wordpress.com/2007/07/31/erlang-vs-stackless-python-a-...
函数式编程,现在已经不成其为卖点了。Erlang最吸引我的是"那种"对并发程序设计的建模方式。从stackless那里看到,原来这个模式叫Actors Model,有年头。
C2的解释:http://c2.com/cgi/wiki?ActorsModel
这篇文章非常好看:http://www.cypherpunks.to/erights/history/actors/AIM-410.pdf
这篇也好看,就是太玄虚了点:http://www.cypherpunks.to/erights/history/actors/AIM-691.pdf
好吧……Ruby咋样呢?继续人肉搜索……要说Ruby(和/或Python)社区从Erlang那里得到什么,直接转过去是可能性不大滴,主要还是(1)学习
Erlectricity是一个bridge:http://code.google.com/p/erlectricity/
Rebar是另一个bridge,成熟度更低:http://rubyisawesome.com/2007/4/30/calling-erlang-from-ruby-teaser
Omnibus实现了Actors Model,成熟度也很低:http://groups.google.com/group/ruby-talk-google/browse_frm/thread/ec4...
拿着Omnibus玩了一会儿。这个语法写出来就等而下之了。看了看源代码,没有什么奇妙的,只是把Thread封装了一下而已。倒是future的概念,是用native C代码实现的。
又搞了一段小程序:http://gigix.thoughtworkers.org/2007/10/23/is-concurrent-ruby-better
什么是future? http://www.ps.uni-sb.de/alice/manual/futures.html
听说Ruby 1.9要加入一个叫做Fiber的东西。这个,把语法糖扔掉以后,和Omnibus基本上同一回事……
http://www.infoq.com/news/2007/08/ruby-1-9-fibers
还有一个围绕着Ruby线程模型的讨论。GIL会对并发编程造成什么影响呢?没认真去想。
http://www.infoq.com/news/2007/05/ruby-threading-futures
以上。
--
Jeff Xiong
Software Journeyman - http://gigix.thoughtworkers.org
Open Source Contributor - http://rubyworks.rubyforge.org
Technical Evangelist - http://www.infoq.com/cn/
Is Concurrent Ruby Better?
October 23rd, 2007
Code with The Omnibus Concurrency Library
require 'concurrent/actors'
include Concurrent::Actors
Message = Struct.new :ping, :pong
ping_thread = Actor.spawn do
loop do
Actor.receive do |f|
f.when Message do |m|
puts "PING"
sleep(1)
m.pong << Message.new(m.ping, m.pong)
end
end
end
end
pong_thread = Actor.spawn do
loop do
Actor.receive do |f|
f.when Message do |m|
puts "PONG"
sleep(1)
m.ping << Message.new(m.ping, m.pong)
end
end
end
end
ping_thread << Message.new(ping_thread, pong_thread)
while(true)
puts("WAITING...")
sleep(5)
end
Also, it runs…forever.
Is Stackless Python THE Way?
October 23rd, 2007
Code with Stackless Python
#
# pingpong_stackless.py
#
import stackless
ping_channel = stackless.channel()
pong_channel = stackless.channel()
def ping():
while ping_channel.receive(): #blocks here
print "PING"
pong_channel.send("from ping")
def pong():
while pong_channel.receive():
print "PONG"
ping_channel.send("from pong")
stackless.tasklet(ping)()
stackless.tasklet(pong)()
# we need to 'prime' the game by sending a start message
# if not, both tasklets will block
stackless.tasklet(ping_channel.send)('startup')
stackless.run()
And it runs…forever.



