News for hackers. Stuff that matters.
Re:Crystal: Fast as C, Slick as Ruby by thinkpad20 on Thursday August 04, 2016 @02:28AM (#12223781)
Manual or deterministic memory management might be a must-have for certain usage domains, but for any domain in which one would be using ruby, this seems unlikely, and presumably one could FFI into C when this is the case. There are hardly any languages commonly used in industry which don't have GC (essentially just C/C++). And many of these garbage-collected languages are capable of blazingly fast code with a small memory footprint.

Regardless, for a language which is meant to operate in the same domain as ruby and be as easy and declarative, not having a GC would be a puzzling decision.

As a side note, I'm curious what areas you are programming in where the presence of a GC is such a downside. Having written almost exclusively in garbage-collected languages over the last few years, it's something I almost never think about (and happy not to). Of course I don't deny that stricter memory control is sometimes necessary.

Re:Crystal: Fast as C, Slick as Ruby by fauigerzigerk on Thursday August 04, 2016 @04:00AM (#12224116)
Crystal seems to be targeted at a domain where ruby is not fast enough. That includes domains where GC is a problem.

A tracing GC means that you either have to deal with potentially long GC pauses or you need a lot of extra free memory at all times to give the GC time to catch up before running out of memory [1].

Go says it can achieve 10ms max pause time using 20% of your CPU cores provided you give it 100% extra memory. In other words, memory utilisation must be kept below 50%.

Cloud/VPS prices scale roughly linearily with memory usage. So using a tracing GC doubles your hardeware costs. Whether or not that is cheap depends entirely on what share of your costs is hardware cost and how much productivity gain you expect from using a tracing GC.

I would be very interested in learning how much CPU and memory overhead Swift's reference counting has, because in terms of productivity Swift is certainly competitive compared to languages using a tracing GC.

[1] Azul can do pauseless, but I don't know exactly what tradeoffs their approach makes. Their price is too high for me to even care.

Re:Crystal: Fast as C, Slick as Ruby by yxhuvud on Thursday August 04, 2016 @05:06AM (#12224332)
Note though that a lot of the problems with GC in crystal can be worked around by replacing classes with structs. The latter are passed by value and allocated on the stack. There is also access to pointers and manual allocation if that should be needed (though that will end up with roughly the same lack of memory safety as in C) to optimize a hotspot.
Re:Crystal: Fast as C, Slick as Ruby by jerven on Thursday August 04, 2016 @05:53AM (#12224475)
For the JVM Shenandoah GC [1] can do so as well (or at least very low consistent pauses) and is available via EA builds or the OpenJDK in fedora 24 [2].

This is with pointer happy java code, not with special effort to have pointer less data.

[1] http://openjdk.java.net/jeps/189 [2] https://fedoraproject.org/wiki/Changes/Shenandoah

Re:Crystal: Fast as C, Slick as Ruby by quotemstr on Thursday August 04, 2016 @12:15PM (#12226537)
> The key to performing concurrent evacuation is having the Java Threads and the GC threads agree on the location of objects. This is accomplished in Shenandoah by the use of a Brooks forwarding pointer. All reads by the Java Threads indirect through this forwarding pointer. All writes to objects in targeted regions must first copy the object and then write to the object in its new location.

I'm a bit surprised that indirection is efficient enough to be worth the trouble (since you need reads and writes to branch for the indirected-object case), but I can't argue with results.

Re:Crystal: Fast as C, Slick as Ruby by mike_hearn on Friday August 05, 2016 @09:00AM (#12231921)
Bear in mind that's a conceptual description. The read/write barriers are implemented as compiler node graphs and thus can be optimised.
Re:Crystal: Fast as C, Slick as Ruby by Taek on Thursday August 04, 2016 @04:08AM (#12224146)
If you are on a server do you need 10ms max pause time? For most applications running go on a remote machine, 25ms should be in the realm of acceptable.
Re:Crystal: Fast as C, Slick as Ruby by sitkack on Thursday August 04, 2016 @04:35AM (#12224245)
Re:Crystal: Fast as C, Slick as Ruby by fauigerzigerk on Thursday August 04, 2016 @04:19AM (#12224190)
True, but I don't know how much that would buy us in terms of memory utilisation and CPU usage.
Re:Crystal: Fast as C, Slick as Ruby by krzat on Thursday August 04, 2016 @04:12AM (#12224161)
People want non-GC language because everyone already has GC language that their are comfortable with.

So basically C/C++ replacement is the only niche that is left to fill. It would be even better if new language could replace even GC-languages, so I can can write fast low level libraries or websites in single language, without sacrificing productivity. That would be the Holy Grail I guess.

Re:Crystal: Fast as C, Slick as Ruby by kminehart on Thursday August 04, 2016 @09:25AM (#12225298)
On the other hand, Go has an excellent garbage collector, and really seems to fill the niche for low-level libraries and programs.

It's also quite a joy to program in, and I'm a JavaScript developer, so I'm coming from the other side of the spectrum.

Re:Crystal: Fast as C, Slick as Ruby by tyoverby on Thursday August 04, 2016 @11:29AM (#12226170)
I'd argue that Go is much closer to Javascript than it is to C/C++.
Re:Crystal: Fast as C, Slick as Ruby by pjmlp on Thursday August 04, 2016 @12:05PM (#12226473)
I think Niklaus Wirth would disagree.
Re:Crystal: Fast as C, Slick as Ruby by lmm on Thursday August 04, 2016 @12:13PM (#12226519)
Have you ever used a language with a decent type system though? I couldn't stand to use Javascript or Go at this point.
Re:Crystal: Fast as C, Slick as Ruby by kminehart on Thursday August 04, 2016 @12:38PM (#12226720)
Of course. I've used C pretty extensively, Java enough to hate it, and C#.

I consider myself a javascript developer because that's what I've done my best work in and that's what I enjoy the most.

Re:Crystal: Fast as C, Slick as Ruby by lmm on Thursday August 04, 2016 @06:37PM (#12228946)
I wouldn't really consider any of those decent (certainly not C or Java), unless C# got sum types when I wasn't looking.
Re:Crystal: Fast as C, Slick as Ruby by banachtarski on Thursday August 04, 2016 @01:17PM (#12227045)
He said decent type system, not static one.
Re:Crystal: Fast as C, Slick as Ruby by smnplk on Thursday August 04, 2016 @02:18PM (#12227429)
How can someone enjoy javascript ? Even closures are not done right and now they added classes. Just what we need sigh
Re:Crystal: Fast as C, Slick as Ruby by kminehart on Thursday August 04, 2016 @02:34PM (#12227540)
I agree, classes are silly in JavaScript. It just masks the prototype and creates ambiguity; using the prototype effectively is part of being a good JavaScript developer.

I understand the hate and everything but honestly I think it presents a fun and refreshing way of solving problems.

Also npm is pretty awesome, aside from how massive the node_modules folder gets.

Re:Crystal: Fast as C, Slick as Ruby by kminehart on Thursday August 04, 2016 @02:17PM (#12227417)
C, Java, and C# have decent type systems, especially compared to JavaScript.
Re:Crystal: Fast as C, Slick as Ruby by smnplk on Thursday August 04, 2016 @02:35PM (#12227551)
They wouldn't say C is "weakly typed" if its type system was decent :)
Re:Crystal: Fast as C, Slick as Ruby by lmm on Friday August 05, 2016 @04:45AM (#12230849)
No sum types, no higher-kinded types, huge verbosity in declaring a new type. I'm talking something like OCaml/F#/Scala/Haskell.
Re:Crystal: Fast as C, Slick as Ruby by mike_hearn on Friday August 05, 2016 @09:01AM (#12231928)
The type systems of Java and C# are OK. C is not even in the same league.
Re:Crystal: Fast as C, Slick as Ruby by ghayes on Thursday August 04, 2016 @03:08AM (#12223921)
One of the largest areas of concern is for real-time systems (systems which fail if they do not respond within some small time threshold). Most GC involves stopping the world to perform the GC which can pause your program's execution for some number of milliseconds. If GC pauses exceed your real-time requirements, you're out of luck.

Some languages, like erlang, do slightly better by garbage collecting erlang processes individually, so other erlang processes can continue running during GC.

Re:Crystal: Fast as C, Slick as Ruby by Matthias247 on Thursday August 04, 2016 @01:05PM (#12226957)
For hard realtime systems it actually doesn't matter anymore. These are mostly implemented with a "don't allocate at all" strategy, since every allocation is not determistic. Therefore things are mostly statically allocated and bounded. And maybe there are some objects pools are around. You can do this in Go in the same way as in C. The only question there is if the GC will still run in the respective languages if no allocations happen through the user (e.g. because the runtime could do allocations in the background for it's housekeeping).
Re:Crystal: Fast as C, Slick as Ruby by mike_hearn on Friday August 05, 2016 @09:03AM (#12231939)
Yeah, the idea that malloc/free "don't pause" can only be based on not understanding how mallocs actually work. Advanced mallocs are often even multi-threaded and do some work on background threads.

Hard-realtime is always "allocate everything up front". It has to be. Allocation of dynamic sizes is not a problem you can make fully deterministic.

Re:Crystal: Fast as C, Slick as Ruby by Svenskunganka on Thursday August 04, 2016 @03:31AM (#12224000)
This is known, but it's always possible to overcome these situations and its part of the language maturing. Golang has already had its run with optimizing their GC for real-time systems. Twitch uses Golang for their IRC chat, and they've taken the Golang GC on a journey which you can read about here: https://blog.twitch.tv/gos-march-to-low-latency-gc-a6fa96f06...

Crystal will at some point also be forced to optimize their GC for these cases, although it currently uses an out-of-the-box GC called Boehm-Demers-Weiser conservative garbage collector http://www.hboehm.info/gc/ which they have acknowledged they need to replace sooner or later.

Re:Crystal: Fast as C, Slick as Ruby by pcr0 on Thursday August 04, 2016 @03:37AM (#12224026)
The parent comment is referring to hard real-time systems (where not responding within a certain timeframe would lead to catastrophy). We're talking things like pacemakers, anti-lock brakes, industrial control systems.

Regardless of how good GC is you would never use it in a hard real-time system because it is non-deterministic. IRC chat is only soft real-time.

Re:Crystal: Fast as C, Slick as Ruby by adrianN on Thursday August 04, 2016 @04:01AM (#12224123)
Those kinds of systems won't get compilers for something other than C/C++ or maybe Ada for a long time. Usually you're stuck with a compiler from the chip vendor that kinda-sorta supports C.
Re:Crystal: Fast as C, Slick as Ruby by lomnakkus on Thursday August 04, 2016 @05:26AM (#12224384)
Indeed, and you'll probably also need a special-purpose RT OS stack (or have to write your own/go without).

EDIT: I'd also add that this is such a niche[1] area of programming that expecting any mainstream language to meaningfully support it is... optimisitic and that mainstream languages shouldn't try to support it. (Soft real-time may be reasonable, but I believe that can be achieved with GC as demonstrated by the Azul JVM.)

[1] Niche, but obviously important, but perhaps not lucrative enough for anything to displace C or perhaps Ada -- given that these industries tend to be extremely conservative. (I wonder if ATS is used, though. Can't claim it's pretty, but proof seems like it would be a good thing for these systems?)

Re:Crystal: Fast as C, Slick as Ruby by pjmlp on Thursday August 04, 2016 @12:10PM (#12226506)
Special versions of Java also get into this niche. Check the PTC Java compilers or Websphere Real Time one from IBM.

Before Aonix got bought by PTC they had a few contracts for weapons control for missiles and battle cruisers.

Re:Crystal: Fast as C, Slick as Ruby by imtringued on Thursday August 04, 2016 @08:53AM (#12225141)
In those situations you wouldn't even use malloc and simply allocate everything statically.
Re:Crystal: Fast as C, Slick as Ruby by rm445 on Thursday August 04, 2016 @04:08AM (#12224145)
Just as a point of interest, I believe there are special forms of garbage collector that are suitable for hard real time systems.

The principle is to regularly use a bounded amount of time for collecting - in line with the latency requirements for the whole system. I think the relevant term is 'tick tock', as in tick - compute, tock - collect.

Re:Crystal: Fast as C, Slick as Ruby by friendzis on Thursday August 04, 2016 @04:26AM (#12224214)
The thing about hard real time systems is that they must be predictable, which is quite wide term. Predictable memory utilization, predictable computation cost, predictable response time. In an attempt to at least fit into these requirements GC must be "passive", on-demand i.e. callable from code. Even with bounded collect times, number of collectings must be predictable/controlled to predict computational cost/time of code paths. And that becomes not much different from manual memory management.
Re:Crystal: Fast as C, Slick as Ruby by _pmf_ on Thursday August 04, 2016 @06:04AM (#12224504)
> Predictable memory utilization, predictable computation cost, predictable response time.

All of these can happen with non-GCd languages through heap fragmentation (i.e. even when correctly allocating and deallocating memory, you can still end up with a fragmented heap.) Tho only way to aviod this is to avoid all dynamic allocation (which is indeed done in a lot of systems) or exclusively use memory pools instead of a traditional heap.

Re:Crystal: Fast as C, Slick as Ruby by chaoxu on Thursday August 04, 2016 @05:33AM (#12224394)
If there is no need for predicting memory utilization, then doesn't real time GC fit the bill? Consider all your know w/e you want execute in time T. A real time GC make sure it always execute in time 2T. For any sequence of operations.
Re:Crystal: Fast as C, Slick as Ruby by Svenskunganka on Thursday August 04, 2016 @03:42AM (#12224041)
Ah, I see what you mean. Thank you for clarifying!
Re:Crystal: Fast as C, Slick as Ruby by bjourne on Thursday August 04, 2016 @01:01PM (#12226920)
Any program running on any non-realtime OS can stop for any number of milliseconds. There are a billion reasons for such interruptions like other processes wanting to run, cleanup phases internal to the OS, memory paging...

If your program stops for 50 ms, do you really care if it was because of a GC cycle or something else? If you really do care, then you are not allowed to target Linux, Windows or OS X all of which are decidedly not real time operating systems.

Re:Crystal: Fast as C, Slick as Ruby by seren on Thursday August 04, 2016 @05:40AM (#12224427)
To answer your last question, Hard real time embedded systems are everywhere in Robotics, Aerospace, Telecommunications, Automotive, Medical devices..

The real time capabilities are not always done in pure SW, there are some FPGAs, but when you do rely on SW, you often can not afford to spend even a few milliseconds in GC. In some case, that would mean killing or maiming someone.

And you are often tied to the HW vendor toolchain for a specific DSP, MCU,.. that is only supporting C or C++. This is a domain that is moving very slowly, currently my most optimistic time table would be able to have vendor support for Rust toolchain in 10 or 15 years but I don't foresee any GC language coming to replace the critical part written today in C or C++.

Re:Crystal: Fast as C, Slick as Ruby by exDM69 on Thursday August 04, 2016 @06:12AM (#12224526)
Even soft real time systems like games or real time networking solutions suffer from non-deterministic GC pauses. Audio processing is another example.

You can get by in a GC'd system if you're careful not to allocate while being in the "hot path", but it's much more difficult than manual memory management (you need to know the internals of the GC algorithm) and interference from other threads may spoil your hard work.

Minecraft is a prime example of annoying (Java) GC pauses causing annoying interruptions. Another one is Kerbal Space Program's choppy audio (from C#/Mono GC). Although these games made millions or billions of dollars regardless, so you might argue it's a non-issue.

> currently my most optimistic time table would be able to have vendor support for Rust toolchain in 10 or 15 years

Not sure how much you'd need changes for the Rust compiler to be able to use it on MCUs and DSPs, but LLVM is more and more common and it might be (almost) enough to have the LLVM backend ported to the target arch. LLVM is moving fast, so for some targets it might be viable much sooner than your estimate.

Re:Crystal: Fast as C, Slick as Ruby by seren on Thursday August 04, 2016 @08:08AM (#12224944)
It was not clear from my post, but what I would like to have is a RTOS with an implementation of the Rust std modules, to be able to develop an application on top of it. As far as I know, no one is working on that.
Re:Crystal: Fast as C, Slick as Ruby by CyberDildonics on Thursday August 04, 2016 @08:14AM (#12224963)
If you write programs with a gc there is always a level which you can't get your hands on to change. If you want to create a piece of a puzzle that is tiny, does one thing, and does it right, like a shared library, a command, a linkable object, or any tiny standalone binary, the gc is always a thorn.

Anything where memory or interactivity needs to be tightly controlled is problematic with a gc. Not only that, but a gc doesn't scale as well with lots of threads. Ultimately you need thread local allocation since you will eventually be bottlenecked by the fact that typical allocation (with malloc, VirtualAlloc, mmap, etc) is protected by a mutex, and deallocation suffers the same fate.

Re:Crystal: Fast as C, Slick as Ruby by wbl on Thursday August 04, 2016 @10:03AM (#12225541)
Except that garbage collected languages generally use per-thread nurseries, so the fast path is a small number of instructions. Having a GC also makes lock-free programming easier.
Re:Crystal: Fast as C, Slick as Ruby by m_mueller on Thursday August 04, 2016 @02:53AM (#12223877)
Obj-C? Or do you count ARC as a GC?
Re:Crystal: Fast as C, Slick as Ruby by exDM69 on Thursday August 04, 2016 @06:15AM (#12224536)
Whether reference counting is GC or not is arguing about semantics.

But correctly implemented reference counting is essentially pause-free. It's consistently "slow", which is better for some cases that unpredictably "fast".

Re:Crystal: Fast as C, Slick as Ruby by m_mueller on Thursday August 04, 2016 @10:22AM (#12225695)
IMO it's not just semantics, rather, GC is too general of a term if it includes ARC. In terms of performance analysis the two are vastly different. One has basically an unbounded worst case but a good average case, the other is the opposite.
Re:Crystal: Fast as C, Slick as Ruby by quotemstr on Thursday August 04, 2016 @12:26PM (#12226633)
Reference counting also has an unbounded worst case: what if you drop the last reference to a very large graph of objects? Then you free the whole thing, which can take an arbitrarily large amount of time.
Re:Crystal: Fast as C, Slick as Ruby by m_mueller on Thursday August 04, 2016 @12:35PM (#12226701)
The main difference there is: You can control the timing of when to pay that penalty. With a full blown GC, if you run into performance issues because of it, you basically have to rearchtect the whole app (with something like memory pools, which you pay by needing more RAM than strictly necessary and with a vastly more complex code). With ARC I can track down a slow memory operation to a single line of code and deal with it there (e.g. by moving the complex object into a singleton). IMO a full GC is just the wrong level of abstraction for anything that's timing relevant, which includes all UI threads.
Re:Crystal: Fast as C, Slick as Ruby by quotemstr on Thursday August 04, 2016 @03:10PM (#12227754)
> IMO a full GC is just the wrong level of abstraction for anything that's timing relevant, which includes all UI threads.

Hard real-time GC systems exist. In these systems, you can prove that pauses last no longer than a certain number of milliseconds. They're definitely applicable to programs with UI.

Can you prove that dropping a reference doesn't free an arbitrarily large number of objects? You can probably convince yourself in specific cases for specific programs that you don't see arbitrarily large refcount-release times, but any change you make to the code might invalidate this analysis.

A hard real-time GC stays hard real time.

Re:Crystal: Fast as C, Slick as Ruby by m_mueller on Thursday August 04, 2016 @04:37PM (#12228279)
I keep hearing about these, but which of the popular GC languages (read: lots of library support) have real time GC? Aren't we talking about industrial RT applications rather than GUIs?
Re:Crystal: Fast as C, Slick as Ruby by SamReidHughes on Thursday August 04, 2016 @04:10PM (#12228103)
You don't have to free the whole thing right away, you (the implementation) can free O(1) things and put the rest on a list to process later.
Re:Crystal: Fast as C, Slick as Ruby by pjmlp on Thursday August 04, 2016 @02:12PM (#12227385)
Any good CS book about GC includes RC as a GC algorithm.

For example, the classical "The Garbage Collection Handbook"

http://gchandbook.org/

Re:Crystal: Fast as C, Slick as Ruby by Ygg2 on Thursday August 04, 2016 @05:20AM (#12224366)
Reference counting is GC. Simple, but GC.
Re:Crystal: Fast as C, Slick as Ruby by dikaiosune on Thursday August 04, 2016 @11:26AM (#12226140)
I agree that to compete with Ruby ergonomics one probably needs a GC. I think part of what I'm getting at is that there are other ways to approach these problems, and aping Ruby isn't necessarily one I prefer. Not to knock Crystal, it seems very cool.

Re: application domains, I've recently been doing some work in CPU/memory constrained applications (not embedded, running big >500GB jobs on HPC clusters), and a GC is unfortunately a non-starter for this kind of data processing.

I have also been watching with great anticipation the work being done on "big data" processing with Rust (https://github.com/frankmcsherry/timely-dataflow) and how that might obviate the need for a GC with the various JVM RAM-hogs which dominate that field.

There are also many areas where people work (many of whom provide the tools that programmers of GC'd languages use for their jobs) which can't admit a garbage collector.

For example, I currently deploy Django code (running on an interpreter that needs to implement, not run on top of, a GC) to a machine with a Linux kernel, running nginx, backed by another machine running PostgreSQL, with caching in Redis. None of those very important tools can reasonably offer the performance needed in a garbage collected language.

For another example, I'm typing this (quite lengthy) response in a low-latency application (a browser) which would also be difficult to implement in a garbage-collected language.

Re:Crystal: Fast as C, Slick as Ruby by mike_hearn on Friday August 05, 2016 @09:05AM (#12231955)
Er, browsers are often implemented in GC languages.

Firefox does the entire UI in XUL and Javascript: all GCd.

Chrome uses a GCd heap for much of its C++ code, and of course the web pages themselves are fully GCd.

Re:Crystal: Fast as C, Slick as Ruby by irq11 on Thursday August 04, 2016 @04:01AM (#12224124)
for any domain using ruby?

you mean like webservers, where GC has been the #1 cause of operational problems for essentially forever?