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.
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.
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.
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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值