728x90
Ruby's Concurrency Nightmare
Ruby on Rails, like most other programming technologies, now finds itself caught in the concurrency quagmire. While RoR has a streamlined focus on the Web application domain, parallelism isn't as limited in terms of domain, platform or application—it's everywhere.

Read James Reinders' counter to this article.

It's interesting that James would extol the virtues of Ruby on Rails in a forum dedicated to discussing concurrency. Why? Ruby on Rails has done a magnificent job of wrangling the complexity of Web applications into a relatively simple model-view-controller concept, but Ruby enthusiasts know that the technology is embarrassingly nonfunctional when it comes to concurrency.

Describing Ruby's "somewhat cooperative" threading scheduler, the official Ruby wiki notes the language's limitations, most shockingly with regards to the 10ms timeout to guarantee atomicity and allow context switching. "On a high-end system, a 10ms timeslice can be an extremely long time; when running a thousand threads, as might be common in a large massively-concurrent application, it would take at least ten seconds for all threads to get a timeslice. Because of the issues associated with this 10ms timeslice and those associated with green threading in general, concurrency in Ruby is typically achieved by running or spawning additional Ruby processes."

Ruby also boasts some native-incompatible threading features such as the ability to kill threads from anywhere in the program, invoke infinite sleep states and enter critical sections at will.

Benjamin Gorlick has written an informative piece on the challenges of threading in Ruby and the hopes its aficionados have for concurrency support in the future. Rails, especially, "was not designed with multi-threading in mind. It was coded completely non-thread safe. There is no reentrancy in many code paths and there is no good locking on important data structures, especially during development mode. It appears rails core is assuming everyone is going to stuff their servers with as much RAM as possible. I recommend 8-16GB of RAM for applications over ten pages (That was a joke, sort of). The RAM solution works until you reach the point of running a huge installation. Assuming you are using mongrel to serve your rails applications, most developers are coming up with hacks to move logic out of rails so the mongrel processes will be lighter. This is done using basic message queues and partly helps this sort of operation. Small shared hosting applications and small projects really suffer from the rails lack of multi-threading implementation."

New tools are on the horizon, however. Gorlick writes about JRuby, a Java implementation of the Ruby programming language that uses Java threads (generally, native OS threads). "Since Java no longer uses green threads, JRuby is able to map one ruby thread to one OS thread," Gorlick explains. "This means it is truly concurrent and the JRuby team is working to make it more safely concurrent in all the core classes."

Another tool is the Rubinius virtual machine for the Ruby programming language. Loosely based on the Smalltalk-80 architecture, Rubinius is written in C and has several concurrency primitives such as Channels, Actors, Tasks and Threads. "Rubinius is able to create and manage 1000 threads instantly with no noticeable overhead. Java and Rubinius allow threads to run concurrently (i.e., access the heap concurrently) and since Rubinius implements the same way Java does so it should have performance much like JRuby, although there are still potential bugs and missing features," according to Gorlick.

New Analogies: Experts Needed
I realize that James was merely admiring the elegant focus of Ruby, not its aptitude for concurrency. But I find it supremely interesting that Ruby on Rails, like most other programming technologies, now finds itself caught in the concurrency quagmire.

Furthermore, RoR is adapted to an MVC convention because the Web application domain doesn't need too many additional models. Parallelism isn't as limited in terms of domain, platform or application—it's everywhere.

James's questions bear repeating: Following Ruby's "Convention over Configuration" mantra, what should be the conventions of parallelism be? Certainly, OpenMP and Threading Building Blocks have gone a long way toward standardizing threading code via libraries of common parallel methods. So, are we already achieving CoC, or could there be additional ways to define standard threading and implicit parallelism while forcing developers to specify only their unconventional programming decisions?

With regards to the other Ruby tenet, "Don't repeat yourself," again one could argue that contributions to parallelism libraries are a way to reduce unnecessary labor. But in the context of Ruby, that also means that information is not sprinkled around in hard-to-trace regions of code, but kept in unambiguous repositories. Is there an analogy for concurrency?

Regardless, parallelism solutions can learn from RoR's domain-specific nature—even if RoR needs a push to enter the age of concurrency.

출처: http://www.devx.com/go-parallel/Article/36235?trk=IntelGo%5FCplusSpecial
================================================================================
루비의 당면 과제에 대해 말하고 있는 듯 보인다.
여기서는 동시성에 대해 언급하고 있는데 Ruby on Rails(ROR)에서 thread를 생성하고 실행할 때 10ms(0.1초)정도 소요된단다. 앞서 루비를 소개할 때 스크립트 언어가 느리다고 했는데 thread는 더 느린가보다. (thread가 수백개정도 생성되는 경우가 web application에서는 흔한 일이니까 치명적일 수도 있다.)

Ruby는 몇몇 native-incompatible threading features를 자랑한단다. 이걸 뭐라고 설명해야 할까? thread를 다룰 때 thread의 상태에 상관없이 해당 쓰레드를 kill할 수 있는 능력이 있단다.(이거 thread를 다룰 때 괘 골치아픈 문제다.)

Benjamin Gorlick란 유명한 사람이 앞으로 Ruby는 동시성에 대한 지원이 있어야 한다고 말했단다. 그사람 말에 따르면 Ruby는 multi-threading을 염두하지 않고 만들어졌다. (쓰레드가 없는 것이 안전하단다.)
많은 code에서 재진입을 허용하지 않고 있으며 그것은 중요한 자료구조들을 보호하는 것에 (특히 개발하는 도중엔 더욱) 좋지 않다. Ruby는 서버컴퓨터에서 RAM의 용량이 충분하다고 생각하고 만들어졌다.(RAM이 부족한 상황을 준비하지 않았다는 말. 10page 이상의 프로그램을 위해 8~16G RAM을 권장한다고 그래놓고 농담이란다.ㅡㅡ;)
이 문제를 해결하기 위해 mongrel를 사용하는 경우가 있다고 하는데 mongrel은 사전에 잡종개라고 되어 있다. 아마 다른 언어를 혼용해서 사용하는 것 같다. 기본적으로 ROR을 사용하지만 thread와 관련된 부분은 다른 것을 사용한다는 것 같다.(내가 알기로는 JRuby를 사용해서 thread는 자바의 thread를 쓰기도 한다.) 이런 mongrel processes는 좀더 가볍단다. 소규모 호스팅 applications와 소규모 프로젝트들은 루비의 멀티쓰레딩때문에 생기는 랙(lack)때문에 고생이 많단다.

JRuby를 쓴 Gorlick가 말하길 새로운 tool들이 떠오르고 있단다. 바로 위에서 내가 말한 내용이다. JRuby에서 Ruby언어를 사용하면서 thread는 JAVA의 thread를 쓴다. 자바가 더이상 green thread를 사용하지 않기 때문에 Ruby의 thread하나당 OS thread하나로 매핑시킬 수 있단다.


다른 tool은 Rubinius virtual machine이다. 루비전용 가상머신 정도 되겠다. Rubinius는 Smalltalk-80 architecture에 기반을 두고 만들어졌기 때문에 C로 만들어졌다. 그리고 몇몇 동시성에 대한 원형을 가지고 있는데 Channels, Actors, Tasks and Threads가 그 예다. Rubinius는 눈에띄는 오버헤드없이 1000개의 thread를 생성하고 관리할 수 있다. JAVA와 Rubinius는 thread가 동시성을 가지도록 해준다.(heap에 동시에 접근할 수 있다는 말이다.) Rubinius는 JRuby만큼의 효율을 보여주지만 여전히 가능한 버그들(potential bugs)을 가지고 있고 특징이 없다(missing features)고 Gorlick이 말했다.
728x90

+ Recent posts