4 ms·
The Unix-style process model has virtues that the OP doesn't seem to grok. It's sometimes helpful to be able to restart one server from a completely clean memo
by rst 16y ago
The Unix-style process model has virtues that the OP doesn't seem to grok. It's sometimes helpful to be able to restart one server from a completely clean memory image without taking the rest of the system down.
Beyond that: the OP sez that "if the whole system is constructed and coded in Lisp, the system is as reliable as the Lisp environment. Typically this is quite safe, as once you get to the standards-compliant layers, they are quite reliable, and don't offer direct pointer access that would allow the system to self-destruct."
But as I write, we've got two Lisp posts on the front page, and the other one[1] is about the performance of code compiled with
(declaim (optimize (speed 3) (safety 0) (space 0)))
That is --- "omit safety checks, just trust me that my array accesses are all in bounds and I'm getting the types right." Code compiled this way is not inherently safer than C, and has to be coded up with equal care.
So, at the very least, the "quite safe" guarantee applies only to code compiled with full safety checks, which typically come with a very large performance hit.
[1] http://news.ycombinator.com/item?id=2192629 http://news.ycombinator.com/item?id=2192629
- neutronicus 16y agoThe other half of his point was specially tuned hardware - the author seems to believe that the type-checking, gc, etc. don't cripple performance the way they do on x86. I don't know if he's right, but that seems to be his point.
- ohyes 16y agoThe idea is that you would have bits in the hardware dedicated to type checking and garbage collection. The example being, that in the assembly language/machine code, you may have a single arithmetic '+' operation. Determining which hardware path to use to add two numbers would be done in the hardware itself. Check the type bits of the numbers and feed it into my ALU. Compare this to an x86 lisp, or compiled C, where 'type' of a 'number' is determined by the assembly code instruction that is used on it. This isn't just a performance improvement, it is also an improvement in the safety of the dynamic language. There are a lot of different things that you could do for garbage collection. You could have in-hardware reference counting, or 'dirty' and 'clean' (or color) bits, for a mark and sweep collector, or 'generational' bits for an ephemeral garbage collector. The idea is that any time you take something out of software, and put it into specialized hardware, you should get a performance improvement. This doesn't mean that the lisp on a chip would be faster than C on a comparable x86 chip, it means that the things that make lisp (and other functional languages) safer and easier to use would be supported in hardware-- therefore not slowing things down as noticeably.
- derleth 16y ago> it means that the things that make lisp (and other functional languages) safer and easier to use would be supported in hardware-- therefore not slowing things down as noticeably. Or, at least, forcing every language implementation on that hardware to use the same safety mechanisms, making some apples-to-apples benchmarks impossible. It would be interesting to see what a C implementation for that hypothetical modern Lisp machine (CADDR?) would look like. A close parallel is AMPC, which compiles C to JVM bytecode.[1] The vendors say it's standards-compliant, and I actually am pretty sure it is, but it doesn't do a lot of the nonstandard things C programmers have come to depend on. For example, the 'struct hack', where you pack data of multiple types into a struct and proceed to index into it as if it were an array (usually an unsigned char array), flatly does not work, due entirely to the runtime type checking done by the JVM. This always seems to lead to major debates over whether it's a very good compiler. [1] http://www.axiomsol.com/ http://www.axiomsol.com/
- sedachv 16y agoThe 'struct hack' is when you leave the type of the last member of a struct undefined (effectively making structs variable-sized). This is actually not a problem for runtime type checking, and is C99 compliant. What causes problems is casting pointers to ints and back, and casting all other crap to chars. This is not standards compliant. Casting ints to pointers will never be type-safe, but one way to get around that is to just ignore the cast, and overload arithmetic operators to work correctly on pointers - the pointers will carry around their type info, and everything should work ok. Casting other crap to chars will never work because it interferes with the way the other crap has its type encoded. Luckily in most cases this casting is done to perform I/O, where you can also just ignore the cast, and specialize the lowest-level I/O functions to dispatch on the actual types. The moral of the story is that you should basically ignore all the line noise the programmer produces about types, and look at the actual objects. This is exactly how Java works, btw. WRT hardware tagging and type checks, there's really no reason to do it on a byte-addressed superscalar processor. If you look at 64-bit Common Lisp implementations today, you'll actually find that they use only about half the available tag bits in each word. The only thing that needs to be boxed is double-floats.
- sedachv 16y ago"The Unix-style process model has virtues that the OP doesn't seem to grok. It's sometimes helpful to be able to restart one server from a completely clean memory image without taking the rest of the system down." Unix processes virtualize real processes by providing indirection to the basic state identifiers of machine code - memory addresses. It's actually much simpler to virtualize a Lisp image - the basic identifiers are symbols. Dynamic binding already lets you do this to parts of the Lisp process. What's needed is an extension to let you do this for packages/modules. "That is --- "omit safety checks, just trust me that my array accesses are all in bounds and I'm getting the types right." Code compiled this way is not inherently safer than C, and has to be coded up with equal care. So, at the very least, the "quite safe" guarantee applies only to code compiled with full safety checks, which typically come with a very large performance hit." With the Common Lisp model of optimization you can do this selectively for parts of your code, and the compiler can ignore your type hints or declarations if it wants to. Array bounds checking can be lifted out of loops because CL arrays come with information about their dimensions. This is a fundamental and unfixable problem in C. Type safety checks are only a performance problem in numeric loops, where it's always possible to provide the compiler with type information so that it can produce provably correct code (if you're looping over arrays of floats, you only have to check the type of the array once outside of the loop - again, this is a fundamental problem of C that is unfixable). People have wasted hundreds of man-years trying to come up with automatic verifiers and safe subsets of C, but the language has so many problems and so few upsides that none of that work is worth it if you want to build reliable systems. Everything about C that is broken is actually very easy to fix, as long as you don't mind not using C.
- astrange 16y ago> With the Common Lisp model of optimization you can do this selectively for parts of your code, and the compiler can ignore your type hints or declarations if it wants to. What if those parts of your code have bugs in them? There's no reason they wouldn't, and whoever's writing file format parsers (fonts, video, JPEG) on your platform is going to turn off safety because it's too slow, even though that code has many attack surfaces.
- 16y ago