`
mryufeng
  • 浏览: 982330 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

why-do-you-like-erlang(转)

阅读更多
原文Url: http://www.clickcaster.com/items/why-do-you-like-erlang
感觉写的非常好(激动中) 和我的经历几乎一样  得出的结论就是: erlang就是我要的 网络应用erlang足够强大了


After having turned into something of an Erlang zealot about two months ago, I've been asked this question quite frequently. I think the best way to explain this is as a corollary to Greenspun's Tenth Rule:
Any sufficiently advanced concurrent C program contains an ad hoc, informally-specified, bug ridden, slow implementation of half of Erlang
I've always had a slight obsession with developing network servers which I intended to process high numbers of concurrent connections. For years and years I tried to do this in C, exploring many different methods of event monitoring, as well as exploring different ways of implementing network servers as described in such books as Unix Network Programming. Sadly I found many of these models and approaches out-of-date. When glibc came out for Linux, threading became the de-facto standard.

Years later, I would try to implement a massively concurrent network server which used a thread-per-request model. By then I had built up quite a home-brewed server framework, with abstract interfaces to many OS facilities, and had written a network server with over 20,000 lines of code.

This is where I began to hit the wall with threads. I had cross-platform threading abstractions between Win32 and pthreads, and had been testing on a number of platforms, and started noticing that on certain platforms I was running into deadlocks, but not others. As the data structures grew increasingly advanced I started to notice more deadlocks. The locking became increasingly more sophisticated, more difficult to debug, and the performance began to decrease as important shared structures needed to be synchronized across all threads.

I began reading more on the overhead of mutexes, which for a performance-obsessed C programmer was quite maddening. Locking a mutex on Win32, for example, required over 600 CPU instructions! I soon came to the realization that the best approach was really one or two threads per CPU core, and that some lighter weight concurrency mechanism which avoids the synchronization problems of threads was the better approach to addressing high numbers of concurrent connections.

I first discovered Knuth's Coroutines as described in The Art of Computer Programming. These provide for lightweight cooperative scheduling without the need of a system call to switch between them. The GNU Pth library implemented something quite similar. I found several similar approaches to userspace threading, including the idea of "microthreads" as implemented by Win32's Fibers and *IX's ucontexts.

The end goal of all of these approaches was separating behavior from function. Each native thread (provided you have more than one) has its behavior isolated into an inner event loop, and the function can be implemented as a microthread.

Provided you got this far, subsequent problems occur when you discover you need a way to send messages between microthreads in a manner which abstracts processing network I/O events, and if you're using threads also lets you send messages between them. I experimented for years with this problem, coming up with some pretty complex abstractions between a multitude of event sources and threading models.

In the end, after years of struggling to build a framework for concurrent network programming, I never reached a point where I was satisfied. I never felt I had truly abstracted away the problems I was trying to solve.

Eventually I realized shared-nothing was the way to go. I became quite enamored with Dan Bernstein's qmail application, which used a collection of shared-nothing OS processes which communicate over pipes in order to process network traffic. Sick of threads, sick of microthreads, sick of trying to synchronize shared information, this is where I ended up. The wisdom of the Unix philosophy: "Do one thing and do it well," finally manifested itself in my eyes.

Finally, I found Erlang. The more I read about it, the more I realized it was an absolutely brilliant implementation of the very model that I had, for years, tried to implement myself. Furthermore, it combined the models of multiple native threads per CPU core which in turn run multiple "microthreads" with a messaging system far more elegant than I ever mustered myself.

For those of you who have not read it, here is a description of Erlang message processing, excerpted from the recently released Programming Erlang:
  1. When we enter a receive statement, we start a timer (but only if an after section is present in the expression).
  2. Take the first message in the mailbox and try to match it against Pattern1, Pattern2, and so on. If the match succeeds, the message is removed from the mailbox, and the expressions following the pattern are evaluated.
  3. If none of the patterns in the receive statement matches the first message in the mailbox, then the first message is removed from the mailbox and put into a “save queue.” The second message in the mailbox is then tried. This procedure is repeated until a matching message is found or until all the messages in the mailbox have been examined.
  4. If none of the messages in the mailbox matches, then the process is suspended and will be rescheduled for execution the next time a new message is put in the mailbox. Note that when a new message arrives, the messages in the save queue are not rematched; only the new message is matched.
  5. As soon as a message has been matched, then all messages that have been put into the save queue are reentered into the mailbox in the order in which they arrived at the process. If a timer was set, it is cleared.
  6. If the timer elapses when we are waiting for a message, then evaluate the expressions ExpressionsTimeout and put any saved messages back into the mailbox in the order in which they arrived at the process.
After reading this I realized this was what I was trying to invent all along. I showed this approach to Zed Shaw (whom you might recognize as the creator of the Mongrel web server) and he expressed that it was quite similar to the way he implemented message handling in his Myriad framework. I'm not going to speak for Zed in terms of Myriad being an ad hoc reimplementation of Erlang, but just point it out to show that when dealing with these sorts of problems long enough people come to the same sort of conclusions about how to solve them.

All that said, I felt naturally comfortable with the Erlang way of doing things. This is how I've been writing programs all along. It's feels so nice to finally find a language that abstracts away all the complex behaviors of concurrent network processing. Furthermore, distributed Erlang and the OTP framework are beyond my wildest dreams in terms of what you can build once the underlying problems are all abstracted away.

Now I can finally stop trying to build an ad hoc, informally-specified, bug-ridden framework, and start focusing on what I've actually cared about all along: the function.
分享到:
评论
5 楼 mryufeng 2007-11-20  
谢谢 zhuzhaoyuan同学翻译了上面的文章, 贴在了erlang-china.org
4 楼 javaeye000 2007-11-02  
ronn 写道
javaeye000 写道
做非并行处理程序的c开发人员没有必要投靠erlang吧?


有空闲时间可以先了解一下erlang有什么优点缺点, 适合用来做什么

接下来如果适合你的需求, 又或者你对它感兴趣, 可以继续深入

对不了解的技术语言等等大概都可以依此对待, 大略了去了解一下自己不熟悉的东西总是有点好处的, 也不至于浪费多少时间


嗯,是这个理。无锁机制的erlang在并行处理领域自然得心应手,不过在其它领域(比如OO)的应用还有待研究。
3 楼 ronn 2007-11-02  
javaeye000 写道
做非并行处理程序的c开发人员没有必要投靠erlang吧?


有空闲时间可以先了解一下erlang有什么优点缺点, 适合用来做什么

接下来如果适合你的需求, 又或者你对它感兴趣, 可以继续深入

对不了解的技术语言等等大概都可以依此对待, 大略了去了解一下自己不熟悉的东西总是有点好处的, 也不至于浪费多少时间
2 楼 javaeye000 2007-11-02  
做非并行处理程序的c开发人员没有必要投靠erlang吧?
1 楼 mryufeng 2007-11-01  
有那位大侠可以把这篇文章翻译下 对于说服为数众多的c开发人员投靠erlang很大帮助。

相关推荐

Global site tag (gtag.js) - Google Analytics