Live data from Hacker News

Why Go Is Not Good (2014)

yager.io

441–450 of 466 posts

Re: Why Go Is Not Good (2014)

#441
post #432

Earlier quoted context omitted.

Targeting the JVM seems like a trending practice nowadays. But I can't really see why it's so great. You'll need to install the JVM to your platform before you can execute anything. You'll also need to install it on your server to serve a web application. I don't know how that works but it sure adds some complexity to the deployment.

If by "install" you mean "unzip", sure. People like JVMs because they provide a lot of services that are really useful, such as: • State of the art garbage collectors, which you can tune for throughput or low pause times (there's a fundamental tradeoff here, there's no one-size-fits-all GC algorithm) • Visual debugging that always works, including remotely • Stack traces that always works • Advanced profiler and moni…

It seems to me that the majority of those features are a result of Java being 20 years old. It's entirely possible Go could achieve or surpass those features by its 20th birthday.

Re: Why Go Is Not Good (2014)

#442
post #438
post #422

Earlier quoted context omitted.

Qt and Gtk's single threaded event loop are akin to what Go calls it's scheduler. That scheduler in Go is also (partially) single threaded, but event handlers run in other threads. Having event handlers run in separate threads is very much supported in both Qt and Gtk (they can't be UI event handlers in quite a few cases, but network events and file reading in separate threads scheduled by the central event loop like…

Go scheduler is not single threaded (whatever that means).

Go's scheduler is a single threaded event loop, like every other scheduler on the planet. It runs, sequentially, in different threads which makes the situation confusing, but it's still single threaded.

It's also cooperative. An infinite loop will effectively kill it (a single infinite loop will kill it before Go 1.2 I believe, but now you need enough of them). More importantly, there's a number of simultaneous syscalls that will kill a go program.

I like about go that it's moving the OS into the application. The thing is, Go's OS is not a very good one. It doesn't have the basic isolation that OSes provide. I hope it will improve.

Re: Why Go Is Not Good (2014)

#443
post #442
post #438

Earlier quoted context omitted.

Go scheduler is not single threaded (whatever that means).

Go's scheduler is a single threaded event loop, like every other scheduler on the planet. It runs, sequentially, in different threads which makes the situation confusing, but it's still single threaded. It's also cooperative. An infinite loop will effectively kill it (a single infinite loop will kill it before Go 1.2 I believe, but now you need enough of them). More importantly, there's a number of simultaneous sysca…

> Go's scheduler is a single threaded event loop

No, it isn't.

> like every other scheduler on the planet

This is not true either. In fact it doesn't make sense. Schedulers are not single threaded event loops. The scheduler (any scheduler) is entered in various scenarios. Sometimes voluntarily, sometimes not. Sometimes the scheduler code can run concurrently, sometimes not. Sometimes the scheduler code can run in parallel, sometimes not.

The Go scheduler is both concurrent and parallel.

> It runs, sequentially, in different threads which makes the situation confusing

I don't know what this statement means. The Go scheduler certainly runs on different threads. So what.

> It's also cooperative.

Actually it's not purely cooperative, it does voluntary preemption, very similar to voluntary preemption in the Linux kernel. The check happens in every function prolog.

> More importantly, there's a number of simultaneous syscalls that will kill a go program.

There's self-imposed user-configurable limit that defaults to 10000 threads for running system calls. The limit has nothing to do with the Go scheduler, it can be set arbitrarily high with no penalty.

> It doesn't have the basic isolation that OSes provide.

The most basic isolation provided by operating systems is virtual memory. Go is a shared-memory execution environment, so this doesn't apply. What other "basic isolation" is provided by operating systems that's missing from Go?

Re: Why Go Is Not Good (2014)

#444

Go is good enough when you're switching from Ruby to Go and all you do is build web-applications. * Its forced syntax stops syntax wars. * Compiling down to one binary makes deployment easy. * Its has concurrency out of the box. * Its insanely fast. * A strong community to hire developers easily enough. Does Haskel/Rust have the same criteria? Shurgs

Speaking for (GHC) Haskell:

- There are curly braces available if you really want them, but people almost always use the whitespace-dependent syntax. There are usually a few ways you can organize your code, but I have never seen any "syntax wars" over Haskell code.

- Haskell compiles down to one binary. Foreign C libraries are linked dynamically by default, if that's being counted.

- Comes with (very cheap) green threads and threading primitives, along with useful concurrency structures (like channels). The standard library includes STM for safer shared mutable memory, and many libraries (like async) are available that extend this. I have not done much Go, but I think forkIO is basically equivalent to "go".

- I couldn't find a whole lot comparing Haskell and Go in particular, but here is one blog post where Haskell was about the same speed as Go, in one narrow application: https://togototo.wordpress.com/2013/07/23/benchmarking-level.... The http server (Warp) used by some web frameworks (Yesod, Scotty, ...) has been noted to be very performant.

- Haskell has a strong, active community. It's not super big, but it seems to me the number of open haskell jobs is smaller than the number of qualified, talented haskell users. Recently there was an issue with a company advertising a non-Haskell job on the haskell-cafe mailing list, because they believed they could get some good developers that way.

EDIT: I posted this without realizing I loaded this page yesterday, and that there were already some responses

Re: Why Go Is Not Good (2014)

#445
post #443
post #442

Earlier quoted context omitted.

Go's scheduler is a single threaded event loop, like every other scheduler on the planet. It runs, sequentially, in different threads which makes the situation confusing, but it's still single threaded. It's also cooperative. An infinite loop will effectively kill it (a single infinite loop will kill it before Go 1.2 I believe, but now you need enough of them). More importantly, there's a number of simultaneous sysca…

> Go's scheduler is a single threaded event loop No, it isn't. > like every other scheduler on the planet This is not true either. In fact it doesn't make sense. Schedulers are not single threaded event loops. The scheduler (any scheduler) is entered in various scenarios. Sometimes voluntarily, sometimes not. Sometimes the scheduler code can run concurrently, sometimes not. Sometimes the scheduler code can run in par…

> I don't know what this statement means. The Go scheduler certainly runs on different threads. So what.

It means that some of the data structures the scheduler examines on every run are shared data, with locking. That makes it effectively single threaded, even if it technically runs on different CPUs (at different times). Put another way it means that it'll never run faster than a single-threaded scheduler would.

> Actually it's not purely cooperative, it does voluntary preemption, very similar to voluntary preemption in the Linux kernel.

You mean preemption inside the linux kernel, in some kernel-space threads ? Because it sounds very different to preemption of applications.

> The check happens in every function prolog.

So it's cooperative. The standard that is normally used is simple : does "for {}" crash("block" if you prefer) some part of the system ? On the linux scheduler the answer is no. In Erlang the answer is no. On the Go scheduler, the answer is yes.

On the linux scheduler with proper ulimits it's bloody hard to crash the system, for instance, forkbombs, memory bombs, ... won't do it. I hope we'll get a language where you can do that too (and the JVM comes quite close to this ideal, some JVMs actually have it even).

Re: Why Go Is Not Good (2014)

#446
post #92

Go is good enough when you're switching from Ruby to Go and all you do is build web-applications. * Its forced syntax stops syntax wars. * Compiling down to one binary makes deployment easy. * Its has concurrency out of the box. * Its insanely fast. * A strong community to hire developers easily enough. Does Haskel/Rust have the same criteria? Shurgs

I believe all of these are good points. The keywords are simple and concise and I believe the language constructs such as interface{} and sub-typing were designed to ensure compilation and running are insanely fast. Google is famous for optimizing their server applications and Go appears to be their "go-to" language of choice for all future web application development.

Interface{} (not interfaces as a whole) and subtyping would make compiling slower. I think sum types and pattern matching would compile faster and be more sensible.

Re: Why Go Is Not Good (2014)

#447
post #445
post #443

Earlier quoted context omitted.

> Go's scheduler is a single threaded event loop No, it isn't. > like every other scheduler on the planet This is not true either. In fact it doesn't make sense. Schedulers are not single threaded event loops. The scheduler (any scheduler) is entered in various scenarios. Sometimes voluntarily, sometimes not. Sometimes the scheduler code can run concurrently, sometimes not. Sometimes the scheduler code can run in par…

> I don't know what this statement means. The Go scheduler certainly runs on different threads. So what. It means that some of the data structures the scheduler examines on every run are shared data, with locking. That makes it effectively single threaded, even if it technically runs on different CPUs (at different times). Put another way it means that it'll never run faster than a single-threaded scheduler would. >…

> It means that some of the data structures the scheduler examines on every run are shared data, with locking.

This is true for every scheduler, not only for the Go scheduler.

> That makes it effectively single threaded

It would limit parallelism to one, if there was a single lock. This used to be the case, but now the locking is more finely grained. But this only matters if there's lock-contention anyway, which is not the case for current Go programs.

> single-threaded scheduler

Again, no such thing as a single-threaded scheduler. Even when talking about systems with a big kernel lock, or with a global scheduler lock. The scheduler is not "single-threaded" or any other term like that because the scheduler is not a thread, it's not an independent thing, it only runs in the context of many other things.

> Put another way it means that it'll never run faster than a single-threaded scheduler would.

As mentioned already, this is not strictly trye for Go, but this matters more for thread schedulers in kernels, less so for the Go scheduler, mostly because the number of threads executing Go code is very restrictive, maximum 32 threads at the moment. It's very likely that this situation might change. For example, the SPARC64 port that I am doing supports 512-way machines, so I'd need to increase the GOMAXPROCS limit. Then maybe we'd have more lock contention (I doubt it).

It's true that the scheduler will probably not scale this well, and will need improvement, but it's unlikely it will be because of lock contention.

> You mean preemption inside the linux kernel, in some kernel-space threads?

Yes, voluntary preemption inside the Linux kernel, not preemption of user-space threads. The Linux kernel can run a mode (common and useful on servers) where it might yield only at well defined points. The name is a misnomer, this is not really preemption, but it's not cooperative scheduling either. It's something in the middle and it's a very useful mode of operation, nothing wrong with it.

> So it's cooperative.

It has the good parts of both cooperative and preemptive scheduling, but yes, it's certainly cooperative.

> The standard that is normally used is simple : does "for {}" crash("block" if you prefer) some part of the system?

Not with GOMAXPROCS > 1, which is now the default on multi-way machines (all machines).

> On the Go scheduler, the answer is yes.

Only sometimes. This is fixable while still preserving voluntary preemption, since the voluntary preemption-check is so cheap that you can do it on backward branches if you really need it. This wasn't done since this wasn't a big problem in practice, even with the old GOMAXPROCS=1 default, but there's room for improvement.

> On the linux scheduler with proper ulimits it's bloody hard to crash the system, for instance, forkbombs, memory bombs, ... won't do it. I hope we'll get a language where you can do that too.

I don't understand the analogy. It is not clear what "crash" means here, and it is not clear how it would apply to a runtime environment. All that stuff, forkbombs, etc, means that you can configure the system so arbitrary code can't affect the system in those particular ways.

But for a language runtime you don't have arbitrary code usually, you control all the code. So I don't understand how any of these would apply.

Coming back to the scheduler. There's always room for improvement. Until relatively recently, the Go scheduler barely scaled past two threads! (although not because of lock contention). Now it scales really well to (at least) 32 threads. There are still improvements to be made, and I am sure they will be made. I was just addressing the "single-thread" issue.

Re: Why Go Is Not Good (2014)

#448

Earlier quoted context omitted.

>Then it needs to stop calling itself a 'systems programming language.' Why must a systems programming language be static and strongly typed? I don't mean to be flippant, but to me, 'systems programming language' means 'a language that facilitates productivity for systems programmers'. By that description, Go certainly qualifies. >Mandatory GC, lack of generics and therefore rampant use of downcasting & duck typing -…

Define "systems programming" (or "systems programmer"). Google's definition seems to be "building large systems". For the types of large systems Google wants to build, Go works very well. But others define it as "building operating systems". Go is horrible for that because of garbage collection and inability to directly access the hardware.

Ah, maybe that's the misunderstanding here.

I can't comment on "building operating systems", but it seems improbable that a GC should never be used in such endeavors.

Re: Why Go Is Not Good (2014)

#449
post #330

Earlier quoted context omitted.

As far as I can tell, conclusions are based on facts about the language as well as other languages. Maps, slices and channels are generics. I'd like to see code in Go written without maps, slices or generics. Go will never implement immutable data structures. Its impossible to write an immutable data structure library without generics. Go will never implement Futures / Tasks / Observables. Its impossible to write Fut…

You absolutely can implement those functions in Go, if you're willing to sacrifice both type safety and performance. e.g., https://godoc.org/github.com/BurntSushi/ty/fun Javascript is unityped, and you can certainly pretend Go is unityped too, by using `interface{}` everywhere. If you linked to a similar set of functions defined in, say, C++, then I'd agree that Go has no real way to achieve something similar. > (err…

You don't need sum types, Result / Optional etc can be implemented in a language without them.

I can implement those in TypeScript too. Its a fast compiler, has a type system, and it supports generics.

Re: Why Go Is Not Good (2014)

#450
post #449

Earlier quoted context omitted.

You absolutely can implement those functions in Go, if you're willing to sacrifice both type safety and performance. e.g., https://godoc.org/github.com/BurntSushi/ty/fun Javascript is unityped, and you can certainly pretend Go is unityped too, by using `interface{}` everywhere. If you linked to a similar set of functions defined in, say, C++, then I'd agree that Go has no real way to achieve something similar. > (err…

You don't need sum types, Result / Optional etc can be implemented in a language without them. I can implement those in TypeScript too. Its a fast compiler, has a type system, and it supports generics.

Sum types are how Result/Option/Maybe/Either are typically implemented. The type system guarantees that inhabitants of the type contain exactly one success value xor one error value, and that accessing the value requires handling both cases, which is checked at compile time.
Post reply on HN