Comment by rtpg
12 years ago
>The problem with C is that a lot of people don't write it well.
There are languages that make it very very hard to write bad code. Haskell is a good example of where if your program type-checks, there's a high chance it's probably correct.
C is a language that doesn't offer many advantages but offers very many disadvantages for its weak assurances. Things like the Haskell compiler show that you can get strong typing for free, and there's no longer many excuses to run around with raw pointers except for legacy code.
> There are languages that make it very very hard to write bad code. Haskell [...]
Sure, but how much slower is Haskell than an equivalent implementation in C? Some quick searching suggests numbers like 1000% slower... and no amount of security is worth a 1000% performance hit, let alone a vague "security mistakes are less likely this way" sort of security. Being secure is useless if your code is so slow that you have to run so many servers you don't make a profit.
Could the Haskell compiler be improved to the point that this isn't a problem? Maybe. Ultimately I think the problem is that Haskell code is very unlike object code, and that makes writing a good compiler very difficult. C is essentially portable assembler; translating it to object code is much more trivial.
> C is a language that doesn't offer many advantages but offers very many disadvantages for its weak assurances.
C offers simplicity. Sure, there are some quirks that are complex, but by and large it is one of the simplest languages in existence. Once you understand the syntax, you've essentially learned the language. Contrast that to Java and C#: you are essentially forced by the language to use this gigantic and complicated library all the time. You are also forced to write your code in pre-determined ways, using classes and other OOP abstractions. In C, I don't have to do that: I can write my code in whatever way I feel makes it maximally readable and performant.
C also offers flexibility: in C, I can make the computer do absolutely anything I want it to in exactly the way I want it to. Maybe I don't like 8-byte pointers on my 64-bit CPU, and I want to implement a linked list allocating nodes from a sparse memory-mapped pool with a known base address using 16-bit indexes which I add to the base to get the actual addresses when manipulating the list? That could be a big win depending on what you're doing, and (correct me if I'm wrong) there is no way to do that in Java or Haskell.
> there's no longer many excuses to run around with raw pointers except for legacy code.
If by "raw pointer" you mean haphazardly casting different things to (void * ) or (char * ) and doing arithmetic on them to access members of structures or something, I agree, 99.9% of the time you shouldn't do that.
Or are you talking about that "auto_ptr" and so-called "smart pointer" stuff in C++? In that case, your definition of "raw pointer" is every pointer I've ever defined in all the C source code I've ever written.
Pointers exist because that's the way computer hardware works: they will never go away. I'd rather deal with them directly, since it allows me to be clever sometimes and make things faster.
>Sure, but how much slower is Haskell than an equivalent implementation in C? Some quick searching suggests numbers like 1000% slower...
With things like stream fusion (http://research.microsoft.com/en-us/um/people/simonpj/papers...) , which I imagine would capture a lot of crypto calls, GHC can generate some very performant code (paper contains examples of hand-written C code being beat by Haskell code, and the C code is far from naive).
There are a lot of tricks at your disposal when you know more about the state of the code. And compilers are usually better than humans in this regard.
That paper is extremely fascinating, thanks for sharing.
As an aside, I'm reasonably sure that GCC can use SIMD instructions for certain bulk memory operations in certain circumstances if you feed it the right -march= parameters... I don't think it's as clever as the techniques in this paper, however.
1 reply →
>no amount of security is worth a 1000% performance hit
Yes it is. Most of the applications I use take roughly 0% of my processor's capacity. I can spare a multiple like that outside of a few hot loops.
Saying 10x slowdown isn't worth it is like saying no one would ever compute on a phone.
Also random BS benchmark http://benchmarksgame.alioth.debian.org/u32/benchmark.php?te... says haskell is at least half as fast as C.
> Most of the applications I use take roughly 0% of my processor's capacity.
We're talking about a server-side vulnerability in OpenSSL here, not applications running on your personal computer.
Roughly speaking, making your server code twice as slow means it will cost you twice as much money to run your servers. Of course, that depends a lot on what exactly you're doing and is obviously not always true... but OpenSSL is a very performance-critical piece of most server-side software in the wild.
If OpenSSL suddenly became twice as slow, it would cost a lot of people a lot of money.
> Also random BS benchmark says haskell is at least half as fast as C.
I never said my "quick searching" was exhaustive. I suspect the relative performance is heavily dependent on what exactly is being done in the code.
8 replies →
"Performance is a quality of a working system." And doubly so for a cryptographic system.
What good is a cryptographic library that's not secure? Worse than no good. If you're not encrypting your data, you (should) be aware of that, and act accordingly. On the other hand, if you think you're encrypting your data...
A 1000% performance hit means that you have to spend 10x more on hardware, and you have to spend more time engineering for scalability. That extra cost outright kills projects in the womb. If the choice is launching something valuable to users and that pulls in revenue but is flawed, even seriously so, and doing nothing because it's just not feasible to do what you want within any reasonable cost/performance metrics... well then, you have your own anthropic principle right there.
> Sure, but how much slower is Haskell than an equivalent implementation in C?
Writing Haskell to generate proven-correct C is an approach that is known to work.
C offers simplicity. Sure, there are some quirks that are complex, but by and large it is one of the simplest languages in existence.
People keep saying this, and it keeps not being true.
C has something like over 200 undefined and implementation defined behaviors. That alone makes it a minefield of complexity in practice.
> Haskell is a good example of where if your program type-checks, there's a high chance it's probably correct.
I really wish people would stop saying this. It's not in the slightest bit true. Making this assertion makes Haskellers seem dangerously naive.
This is especially true in the field of crypto, where timing attacks are a major issue. Knowing that your program will produce the correct result isn't enough, you need to know that the amount of time taken to compute that result doesn't leak information, and I don't think Haskell provides any way to ensure this.
Haskell in fact does the opposite. Changes in compiler version can drastically alter the performance of your code, even changing its O() class.
it's just probably correct ;)
How do I embed your Haskell library in my Lisp program? This is where C shines...it can be used everywhere, including embedded in other programs, now matter what language it's in.
Like this: http://www.haskell.org/ghc/docs/latest/html/users_guide/ffi-.... Haskell's FFI works both ways.
(It's not free: you need to link in the entire Haskell runtime system, which is not small. But you can absolutely do it.)
Cool, thanks for the link. Didn't know this was possible.
> Haskell is a good example of where if your program type-checks, there's a high chance it's probably correct.
For a value of 'correct' that includes "uses all available memory and falls over".