Mongrel2 Almost Valgrind Pure, Bstring Happy
sheddingbikes.com
sheddingbikes.com
Aside from the fact that it'll undoubtedly be a great piece of software, it's informative and interesting to follow along with his progress on his blog and on his fossil repo.
And if what he promises in terms if features and performance comes to fruition, it'll be a fscking awesome server/gift to hack on and hack with.
Cheers, Zed. Keep it up!
I just hope it honestly puts an end to this insistence on "one language to rule them all".
Lua and Tcl were designed with this approach in mind (they expect to be embedded), but you can do it with Python, Ruby, Lisp, Erlang, etc. too.
As I work on the prototype though, I start to figure out if the language I decided at first will work well for it or not. Since I usually throw my first prototype out, with a fixed time to get it working, I'll end up picking a different language or not depending on my experience so far.
First up, I had some unit tests, which are essential if you want to be able to pivot like this suddenly. Second, I knew a lot about the tools I could use so I had a clear idea of how to attack the problem. Finally, it's just a matter of picking the smallest little piece, converting it, and then stepping through all the parts that piece touches. Kind of like spreading a virus.
The world only doesn't end because people are so used to the terrible security record of C apps that they don't even blink when new remote code execution vulnerabilities are found daily. Perhaps someday we'll realize it doesn't have to be this way.
Also, of course the Boehm GC isn't very good. It's ancient and in no way representative of the latest technology in garbage collection. GC can only really be good when it's integrated with the language. A precise generational collector would perform far better but wouldn't be so easy to drop into a C codebase.
(In other words, the conclusion "C is fast and good for apps" is not what you should reach from watching the mongrel2 development. "You can use any language if you have good design and a clue," is.)
I would have picked Haskell. Then I could drop to C when needed, but probably not ever need to. But then what would there have been to blog about? :)
Alright then, if you'd do it in Haskell, why haven't you? I spent about 2-3 weeks so far on Mongrel2 and it already does quite a lot. I figure, hey, Haskell's supposedly so much more bad ass, let's see you get it done. In fact, I'll be you don't even use any of these Haskell web servers as your main web server:
http://www.haskell.org/haskellwiki/Haskell_Web_Server
Thus my point. Language fetishists become distracted by the hype and dogma of their favorite language tribe and then become blind to the evidence. Evidence so far says C makes good web servers. Web servers in other languages tend to need to use C. Lots of great software powers the world and is written in C. Using C does not cause the death of the universe. It isn't hard, or scary, it's actually pretty simple.
After a while, you have to start wondering, is it true that the language is so dangerous, or is it just more marketing?
Since C has been around 1972, it follows that a lot of software is going to be written in C.
I agree with your conclusion but not your reasoning. Try substituting "Lisp" and "1958".
A fair comparison is C to C++ or Java to C#. C has been around longer than C++, and there are more C apps than C++ apps on UNIX. (Windows is another story; MS pushed C++ pretty hard back in the day. Same for Obj-C on Mac.)
Java has been around longer than C#, and there is more stuff written in it, even though it is technically inferior. Time always beats language features.
If you want an accurate measurement, start a totally new project today that depends on nothing. Clone yourself. Then start writing it in C, and in $some_other_language. Then see which one meets your expectations soonest. It will probably be $some_other_language. But add in some dependencies on historical code, and C becomes competitive again.
Standing on the shoulders of a giant is faster, in the short term, than becoming a taller giant.
People have a bad habit of calling any received wisdom they disagree with "marketing". There are people out there far smarter than I am, and possibly smarter than you are (though I'm not in a position to judge), who disagree strongly with what you say, and they're not marketeers. No need to go down that route in this debate.
"State is also a major source of error" is an unsupported claim. Show me any usability study that confirms removing state improves a programmer's source and understanding of the solution.
The truth is, all of the concepts of state free, type systems, assertions, and design by contract are just specific limited cases of a more flexible assertion system. Type systems are a compile time assertion that you are getting a type you expect. Design By Contract are runtime assertions about state of the system. So is assert in C. Removal of state like in Haskell is just a very restrictive design by contract alternative compile time assertion.
If all of these are specific cases of a general assertion system, then none of them cover the complete set of assertions you'd need to truly make "safer" software. You'd need link time assertions (dll hashes and version required, function prototypes required), compile time assertions more flexible than types, and runtime assertions like design by contract.
Unless your language has all of those in an optional way (which would be a pain in the ass to use) then your language is truly no better than C.
As for state, the concerns there are confined primarily to concurrent systems, and about a gazillion people have discussed its problems with greater eloquence than I can muster (Joshua Bloch comes to mind). But you're a great programmer--no sarcasm intended--and if you say you can produce a great concurrent system and still carry around a ton of state then I believe you. I'm genuinely looking forward to the fruits of your labor. Most people, myself included, can't.
The goal isn't to twist yourself or your users into a pretzel trying to build a language that prevents any error whatsoever from occurring, as far as I'm concerned. The goal is to produce a language that shrinks the potential for bad stuff on the downside and encourages good practices (and stays out of your way) on the upside. C did, in its day, accomplish both things admirably, and for some tasks it remains the best tool. It does not, however, follow that all of its shortcomings are in fact virtues, and that those who say otherwise are marketing.
Instead, you want more structured state transitions. A FSM is one way of getting that.
What does "good" mean in this context?
I suspect that technical matters such as deployment and integration with other components is of greater concern (though I also suspect that the kind of language fetishism which looks balefully on the use of anything other than C as a system programming language has some effect).
For example, if you want to parse an HTTP header in Python you have to iterate through either integers, or break it up into smaller strings, or use the really bad tokenizer library. Most languages with immutable strings make fast parsing and "copy on write" semantics difficult, so they're already harder to work with.
Another example is how they screw up sockets. In C sockets are simple, requiring only a few function calls to work with, and then a bunch of error conditions. Everything you get out of them is bytes put into a buffer of your choice. In other languages you have to work with some badly designed OOP layer that makes no sense, exception classes for each errno, randomly sized buffers with no Chord data structure, or an event system like Twisted that gives no ring buffer or state machine functionality.
In the end, implementing the solid core of a web server is just easier in C. I wouldn't want to implement a full blow web app in it, because doing something like a template system is murder (dynamic languages win hands down there). But the core is much easier.
http://www.haskell.org/ghc/docs/6.10.2/html/libraries/networ...
> A precise generational collector would perform far better but wouldn't be so easy to drop into a C codebase.
It's that last part that's key. Without language support at even the basic level, you won't get much better.
As for this "precise generational collector", I doubt it. Like everything, saying you need a GC all the time to be safe is just more boogey man fear mongering. You don't need a GC. They're nice yeah. But if you know the application very well then memory management isn't too big a deal.
Agreed.
A related case is with Objective-C's memory management scheme which isn't a full GC, but lets you scope your memory allocations. It gets you a level of control that is somewhere between a GC and the kind that boost::shared_ptr does ... neither having the "wait for the trashman" problem that GC brings, nor overdoing the reference count touching like boost can get you into.
Obj-C 1 right? I believe Obj-C 2 (on OSX, not iOS) has an optional GC, at least for the objective part. Or would I be wrong?
Boehm is the best garbage collector given its constraints, but that doesn't make it a good garbage collector overall, or even one worth using. I agree that good GC requires language support; what I disagree with is the attitude that people should use C anyway and forget GC because Boehm isn't good.
I, too, choose bstring for strings and used valgrind a lot. It's nice to see I'm not the only one writing C code this way. (Although I don't write much C anymore.)
Sorry, Mr. Shaw, but you are wrong (but I still like you and I'm looking forward to Mongrel2).
RFC 2616 is careful to say 'server' when it means servers and 'client' when it means clients. Section 3.6.1 specifically states that HTTP/1.1 applications (so both clients and servers!) MUST support chunked encoding.
The developers of that Java HTTP client (Jakarta?) seem to have read the spec more thoroughly than you did. :-)
Which brings up another point: HTTP is like the old testament. Wanna kill your brother? Probably find something to support it. Wanna sacrifice a goat? Yep, you could do that. Don't want people to sacrifice goats? Sure, rock on. Want adultery? You could probably find that too. It's got everything depending on what you read, where you read, and what context you take it in.
The HTTP RFC is like that. Want to send chunked encoding mixed inside a keep-alive with request pipelining when you don't really need to? Rock on. Want google web accelerator to hit links without you asking it to (in clear violation of every other part of the browser standard)? Go for it. Don't want people to do that? Cool there's another part.
After a while, you have to go with what's most probable, and just be explicit in your own design about the rest.
I find that statement a tad too optimistic. If you use Valgrind continually (and people really should), you do catch memory misuse in normal situations. It does not say much about how well programs function with 'abnormal' inputs (accidents, exploits).
Given that bugs do happen, even to the best of programmers, would you rather have a buffer overflow or an exception? It depends on the application and context, but it is harder to answer (and get it right) than the author pretends.
I think of valgrind as a GC compiler.
Your programs will still be suspectible to buffer overflows, invalid dereferencing, etc. While, say, Haskell programmers do not have the same problems. Valgrind is no substitute to runtime checks and a proper type system.
That's bad, right? I'm still giggling.