Live data from Hacker News

Go does not need a Java-style GC

erik-engheim.medium.com

211–220 of 226 posts

Re: Go does not need a Java-style GC

#211

Earlier quoted context omitted.

I have addressed similar problems using a typed array of contiguous memory and another array of lengths.

I did try exactly that, but the GC overhead was still prohibitively high for my use case, made because big arrays in practice are composed from shorter non-contiguous arrays to make garbage collection even remotely possible.

Hmmm, if the typed array only contains primitives, the GC isn't looking inside the array. If the thing pointed to, can never contain a pointer, it won't need to be scanned.

Re: Go does not need a Java-style GC

#212

Earlier quoted context omitted.

In general when talking about quantitative subjects, we need to use quantitative measures. I think the author is nearly there, but in general, unless you have data to refute your claims, it should be ignored. I don't say this snarkely, but in a domain where we actually have hard quantitative measures, they should be used and required for argument.

Quantitative measures would be nice, but I would imagine that it's going to be really difficult to quantitatively compare go and java garbage collectors, without a billion other factors about the language/runtime getting in the way.

To yield to non-quantitative reasoning when the difficulty in the measurement goes up, can lead to decisions like the one to launch Challenger space shuttle in 1986. Difficulty doesn't change the science or the questions we ask. Politics doesn't make something true.

I am not even talking about GCs, I am talking about the intellectual rigor we should use when discussing quantitative subjects. To do anything else is to practice magic.

Research papers on GCs will outline the comparisons and metrics they use to study GC algorithms.

Re: Go does not need a Java-style GC

#213
post #206

Earlier quoted context omitted.

Do it. Show me that Java can avoid allocating/collecting the Tree objects. Go has no indirection for the Tree objects, in this example. The Trees are contiguous in memory. Measure the performance. I have no garbage collection performance problems in the various large Go projects I have worked on. But I am also a competent programmer, so "your mileage may vary".

For the time being, until Valhalla is finalized, Java can emulate this approach simply by using an int array. After making the modifications, on my local machine, Java ran as low as ~820ms, compared to golang's ~932ms. golang's GC is no silver bullet as we see here: * https://blog.discord.com/why-discord-is-switching-from-go-to... * https://news.ycombinator.com/item?id=21670110

Thanks for doing the test!

Re: Go does not need a Java-style GC

#214
post #206

Earlier quoted context omitted.

For the time being, until Valhalla is finalized, Java can emulate this approach simply by using an int array. After making the modifications, on my local machine, Java ran as low as ~820ms, compared to golang's ~932ms. golang's GC is no silver bullet as we see here: * https://blog.discord.com/why-discord-is-switching-from-go-to... * https://news.ycombinator.com/item?id=21670110

Thanks for doing the test!

No problem. I'll try to download a Valhalla JVM build and see how it fairs.

Re: Go does not need a Java-style GC

#215
post #118

Earlier quoted context omitted.

How have you found Go in contrast to Java. Is the simplicity worth it?

yes. golang is actually less restrictive than java. and avoids a ton of the bullshit abstractions you see in every java code base.

>ton of the bullshit abstractions

Not sure how that's the Java's problem. Most of these abstraction come older frameworks. You can have these same abstraction/design pattern in Go also.

Re: Go does not need a Java-style GC

#217
post #214

Earlier quoted context omitted.

Thanks for doing the test!

No problem. I'll try to download a Valhalla JVM build and see how it fairs.

How does Java do without using an array of ints, or Valhalla? In other words, what's the cost of Java's forced indirection?

What happens if you use

  pool := make([]Tree, 0, 256)
instead of

  var pool []Tree
in the Go so it doesn't waste time growing tiny slices?

Re: Go does not need a Java-style GC

#218
post #214

Earlier quoted context omitted.

No problem. I'll try to download a Valhalla JVM build and see how it fairs.

How does Java do without using an array of ints, or Valhalla? In other words, what's the cost of Java's forced indirection? What happens if you use pool := make([]Tree, 0, 256) instead of var pool []Tree in the Go so it doesn't waste time growing tiny slices?

After making the change in the golang version, I saw it go as low as 867.61ms.

The JVM is very good at inlining. It's not perfect obviously, but in this benchmark just using an `int[]` wrapped in a class (similar to an ArrayList) produced quicker results than golang. I'm not surprised, since the golang compiler doesn't generate the greatest code.

I tried with Valhalla, with the following array wrapper, and I saw it run as quick as 667ms.

    stretch tree of depth 22  check: 8388607
    2097152  trees of depth 4  check: 65011712
    524288  trees of depth 6  check: 66584576
    131072  trees of depth 8  check: 66977792
    32768  trees of depth 10  check: 67076096
    8192  trees of depth 12  check: 67100672
    2048  trees of depth 14  check: 67106816
    512  trees of depth 16  check: 67108352
    128  trees of depth 18  check: 67108736
    32  trees of depth 20  check: 67108832
    long lived tree of depth 21  check: 4194303
    0.667455718

This is the Java Tree and array wrapper code I used

    inline class Tree {
     public int left; 
     public int right;

     public Tree(int left, int right) {
      this.left = left;
      this.right = right;
     }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // Copyright (c) 2001, Eric D. Friedman All Rights Reserved.
    //
    // This library is free software; you can redistribute it and/or
    // modify it under the terms of the GNU Lesser General Public
    // License as published by the Free Software Foundation; either
    // version 2.1 of the License, or (at your option) any later version.
    //
    // This library is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU Lesser General Public
    // License along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ///////////////////////////////////////////////////////////////////////////////
    
    final class TIntArrayList {
     protected Tree[] _data;
     protected int _pos;
     public TIntArrayList() {
      _data = new Tree[0];
      _pos = 0;
     }
    
     public void ensureCapacity(int capacity) {
      if (capacity > _data.length) {
       int newCap = Math.max(_data.length 

Re: Go does not need a Java-style GC

#219
post #76

Earlier quoted context omitted.

> So Java has the fastest GC for this test, 2.48 secs vs 12.23 secs for Golang. Further not mentioning memory used Java/Go programs makes it very fair comparison. Because GC perf does not depend on memory allocated.

Right now in the datacenter CPU usage is considerably more expensive than RAM usage. Ram consumes comparatively little power, whereas burning hot CPUs+GPUs are the reason datacenters are favored near cooling water and power stations. 2.48 vs 12.23 seconds for Java and Go is a big deal for how many solar panels or tons of coal are needed to run an app on Xeon or Epyc instances, whereas 1.7GB vs 0.4GB for Java and Go,…

Just for fun set the Java heap to .4 Gigs or use GOGC to set the Go heap to 1.7 Gigs. If Go is faster then try some other sizes and draw a graph to see what the lines look like.

Re: Go does not need a Java-style GC

#220

Earlier quoted context omitted.

> If you have a lot of microallocations, then your program is going to be slow regardless of you using manual memory management, RAII or a tracing GC. No, that's no true. Tracing GC is mainly O(f(live stuff)), not O(f(dead stuff)), so there is basically no problem making lot's of garbage if you don't have any exotic latency requirements. > Another reason is eliminating unnecessary pointer indirection, which helps mak…

> No, that's no true. Tracing GC is mainly O(f(live stuff)), not O(f(dead stuff)), so there is basically no problem making lot's of garbage if you don't have any exotic latency requirements. That's true for copying generational garbage collectors. You only need to copy the live stuff and forget everything else. But in e.g. a mark-sweep collector, sweeping dead stuff takes time. In particular, e.g. Chromium's Oilpan c…

> That's true for copying generational garbage collectors. You only need to copy the live stuff and forget everything else. But in e.g. a mark-sweep collector, sweeping dead stuff takes time. In particular, e.g. Chromium's Oilpan can take a long time in the sweeping phase, when there are lot of dead objects.

Sure. I got confused why people do these designs which seem to me to be an awkward compromise, but yes they exist.

> But when there are a lot of microallocations, you also have a lot of live objects, which could otherwise be just a single object in the case of e.g. big arrays.

Not necessary in general. Sure with the array, and I agree that is a bit silly. But there is no general law that more microallocations means more live data.

> Hmm, seems I highlighted the wrong aspect....

Sure those things sound sensible. I don't mean to disagree with any of that.

Post reply on HN