Live data from Hacker News

Carp – A statically typed Lisp, without a GC, for real-time applications

github.com

81–90 of 139 posts

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#81
post #7

There is also interesting CL implementation that is based on the LLVM framework - Clasp[1]. It can be natively compiled and designed for performance. [1] https://github.com/clasp-developers/clasp

CLASP is a really interesting project. For one, it's created and written by a Chemistry PhD researcher (Christian Schafmeister), not someone with a traditional CS background. For another, it's one of the few languages that has ever attempted to interface with C++ at the template level - you can instantiate C++ template classes from CL, and catch C++ exceptions etc. For yet another, he does compacting garbage collecti…

I guess it helps that it is pretty much a Lisp for the research work that they are doing, instead of trying to cater to everyone.

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#82
post #39
post #7

There is also interesting CL implementation that is based on the LLVM framework - Clasp[1]. It can be natively compiled and designed for performance. [1] https://github.com/clasp-developers/clasp

Last I checked SBCL and CCL (both open source native compiled CL implementations) are quite a bit faster than Clasp. However, if you are primarily e.g. calling computational chemistry libraries written in C++, Clasp is the way to go. It's the only non-C++ language implementation I know of with actually usable C++ support.

C++/CLI comes to mind, as means to merge .NET and C++ worlds together.

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#83
post #68

Earlier quoted context omitted.

> A non-blocking write should just copy the data to the socket buffer, definitely not taking milliseconds. That's the theory, right? It could be I measured something wrong, but sometimes dozens of ms is what I got, and I concluded that non-blocking I/O avoids indeterminate blocking (such as reading from a TCP socket until the sender sent N bytes) but does it completely avoid taking in-kernel locks etc? Probably not.…

>I didn't find any other measurements on the internet, please point me to them if you find them. It has been years since I have written thousands sockets servers (used in forex), yet even a couple milliseconds per write would have made the entire operation useless. >another explanation could be false sharing effects that I didn't know well at the time. False sharing sucks, of course, but milliseconds seems way way to…

Correction, one of Hotspot's GC implementations, there are plenty of Java implementations to chose from.

Including ones with soft real time GC for performance critical deployments like PTC and Aicas.

https://www.ptc.com/en/products/developer-tools/perc

https://www.aicas.com/wp/products-services/jamaicavm

Anyone picking a traditional JVM for such workloads is doing it wrong.

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#85

This is interesting, but I believe a big point of LISP is actually having a live system that can be introspected, and GC is part of making that work. In the end isn’t this just but with s-expressions?

S-expressions also enable proper macros, as long as it has them, it's already ahead of .

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#86
Of course the obvious question is "What kind of memory management does it use?"

It uses a "linear" (actually affine) type system for memory management, with borrowed refs similar to Rust, but evidently without tracking mutability: https://github.com/carp-lang/Carp/blob/master/docs/Memory.md

The omission of the kind of mutability tracking that eases multithreading seems like a significant drawback for its target application domain.

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#87
post #83
post #68

Earlier quoted context omitted.

>I didn't find any other measurements on the internet, please point me to them if you find them. It has been years since I have written thousands sockets servers (used in forex), yet even a couple milliseconds per write would have made the entire operation useless. >another explanation could be false sharing effects that I didn't know well at the time. False sharing sucks, of course, but milliseconds seems way way to…

Correction, one of Hotspot's GC implementations, there are plenty of Java implementations to chose from. Including ones with soft real time GC for performance critical deployments like PTC and Aicas. https://www.ptc.com/en/products/developer-tools/perc https://www.aicas.com/wp/products-services/jamaicavm Anyone picking a traditional JVM for such workloads is doing it wrong.

What I meant is that low latency GC is sort of a commodity/mainstream now. Not advising to use java or a specific JIT+Collector.

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#88

For the history buffs: Pre-Scheme: A Scheme Dialect for Systems Programming Richard A. Kelsey, 1997 Abstract Pre-Scheme is a statically typed dialect of Scheme that gives the programmer the eciency and low-level machine access of C while retaining many of the desirable features of Scheme. The PreScheme compiler makes use of type inference, partial evaluation and Scheme and Lisp compiler technology to compile the pro…

The letter combination "fi" seems to have been deleted throughout your quote, there. Perhaps it was a ligature in the original.

I was thinking it lacks a foreign function interface (FFI)

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#89

This is interesting, but I believe a big point of LISP is actually having a live system that can be introspected, and GC is part of making that work. In the end isn’t this just but with s-expressions?

S-expressions also enable proper macros, as long as it has them, it's already ahead of .

I guess so, I think my point is: are s-expression enough to qualify as a LISP?

Re: Carp – A statically typed Lisp, without a GC, for real-time applications

#90
post #61

Earlier quoted context omitted.

As long as you forbid or mark cycles (…or ignore the problem) lifetime analysis can be done statically. Which is better anyway. Automatic memory management doesn't need a GC.

It's really surprising that it's rare in functional languages. Immutability seems like it should guarantee no cycles (?), so reference counting could be used.

Reference counting is usually very expensive, because even reading a variable updates the reference count, and ending a scope involves testing the reference count of every variable defined inside the scope and conditionally deallocating the referent.

Without reference counting, here's the end of a hairy function scope that deallocates 15 local variables and restores two callee-saved registers:

        11a6:       48 83 c4 78             add    $0x78,%rsp
        11aa:       5b                      pop    %rbx
        11ab:       41 5e                   pop    %r14
        11ad:       c3                      retq
Now imagine looping over 15 local variables to decrement each reference count, test it, and do a conditional jump based on the result; if that's open-coded, your epilogue is humongous, and if it's in a reference-count-decrementing subroutine, it's going to have mispredicted branches all over the place, costing you maybe 15 cycles each, a total of about 100 cycles for this function. We're talking about adding an order of magnitude of cost to subroutine call, or more. (I think this function doesn't really need 15 local variables; that's the compiler's fault.)

This gets worse with multithreading, because writing to the same reference count on different cores would even in the best case require one core stealing the cache line from another in order to modify it, which may stall the core; but often even an atomic reference count increment is more expensive even than that because it involves a memory barrier.

Reference counting can become reasonably cheap if it's done at large granularity (filesystem files or COM objects, not conses); if you can elide almost all of the reference-count updates, as in Rust; or if your language runtime is just so dog-slow at everything that the extra cost of reference counting isn't that important, like CPython.

30 years ago or more, before generational GC had gone mainstream, reference counting was a more reasonable choice, because GC was going to be very slow in any case, and ref counting at least used less memory—especially important on machines without cache or virtual memory.

(Purely immutable (applicative) languages like Haskell and Miranda are usually lazy, since that's the payoff for completely abjuring side effects. But lazy evaluation is implemented at the machine level by mutation.)

Post reply on HN