Live data from Hacker News

Why the New V8 Is So Damn Fast

nodesource.com

211–220 of 237 posts

Re: Why the New V8 Is So Damn Fast

#211
post #77

Earlier quoted context omitted.

TypeScript can do runtime checks like this! Granted it uses a TypeScript framework (similar to AJV) that both does the runtime checks and preserves type information for your IDE and type checker. I wrote about it here: https://medium.com/@stevenbradleyconsulting/from-0-to-type-s...

Aw, man - I'd hoped you'd found something to make this less of a stone-cold pain to do. Instead, it's io-ts again. Which is...interesting...but it really sucks to actually use when you have to manually define every in/out yourself. It's 2018. There's no good reason TypeScript can't emit the type information to just build these (and I don't really mean decorator metadata).

You can add another build step right after the `tsc -w` compilation phase, which takes your .ts files, parses them to find our your types, and emits runtime code that checks your types. That's what you're describing that TypeScript should be doing on its own. But I don't see why you'd want to do this instead of using io-ts? This is more complicated overall.

Re: Why the New V8 Is So Damn Fast

#212
post #194
post #174

Earlier quoted context omitted.

In JS for-in loop enumerates keys in the insert order. So {x,y,z} is different from {z,x,y}

AFAIK, that's not true; the spec doesn't guarantee that it iterates in insertion order, it's just how it's commonly implemented in browsers.

Nope, they should be iterated in their defined order: https://tc39.github.io/ecma262/#sec-ordinaryownpropertykeys

I think they added this with ES2015.

Re: Why the New V8 Is So Damn Fast

#213

Earlier quoted context omitted.

Not sure what you mean by imprecise, but Go’s GC does trade throughput for latency. The overhead still isn’t huge if only because there is so much less garbage than in other GC languages. I’m also surprised by your cache misses claim; Go has value types which are used extensively in idiomatic code so generally the cache properties seem quite good—maybe my experience is abnormal?

>Not sure what you mean by imprecise It's a rigid term: https://en.wikipedia.org/wiki/Tracing_garbage_collection#Pre... perf shows how much time does GC eat, and that's quite a lot. Thus in the majority of benchmarks go lags behind java or on par with it at best. >there is so much less garbage than in other GC languages That is not true since strings and interfaces are heap allocated thus the only stack allocated obj…

> It's a rigid term

Ah, neat! I learned something. :)

You’re mistaken about only numbers and simple structs being stack allocated. All structs are stack allocated unless they escape, regardless of their contents. Further, arrays and constant-sized slices may also be stack allocated. I’m also pretty sure interfaces are only heap allocated if they escape; in other words, if you put a value in an interface and it doesn’t escape, there shouldn’t be an allocation at all.

Re: Why the New V8 Is So Damn Fast

#214

Earlier quoted context omitted.

>Not sure what you mean by imprecise It's a rigid term: https://en.wikipedia.org/wiki/Tracing_garbage_collection#Pre... perf shows how much time does GC eat, and that's quite a lot. Thus in the majority of benchmarks go lags behind java or on par with it at best. >there is so much less garbage than in other GC languages That is not true since strings and interfaces are heap allocated thus the only stack allocated obj…

> It's a rigid term Ah, neat! I learned something. :) You’re mistaken about only numbers and simple structs being stack allocated. All structs are stack allocated unless they escape, regardless of their contents. Further, arrays and constant-sized slices may also be stack allocated. I’m also pretty sure interfaces are only heap allocated if they escape; in other words, if you put a value in an interface and it doesn’…

Both arrays and interfaces are heap allocated. Slice is just a pointer to a heap allocated array.

Structure could be stack allocated, but any of it's fields would not if there is anything but a number.

A trivial example:

https://segment.com/blog/allocation-efficiency-in-high-perfo...

    func main() {
            x := 42
            fmt.Println(x)
    }

    ./main.go:7: x escapes to heap
So a trivial interface cast leads to allocation.

Re: Why the New V8 Is So Damn Fast

#216

Earlier quoted context omitted.

It’s not native vs VM, but rather “has stack semantics/value types” vs “no stack semantics/value types”. In particular, OCaml’s standard implementation is a native, not VM. Also worth calling out Go, which is rather unique in that it has stack semantics but it also has a garbage collector, so it’s kind of the best of both worlds in terms of ease of writing correct, performant code.

Regarding your last point, Crystal has the same features as go in that regard, while at the same time being vastly more expressive. This mostly due to the standard library in Crystal being so nice for work with collections (which perhaps isn't surprising as the APIs are heavily influenced by Ruby). Blocks being overhead free is another necessary part for this to work well.

Yeah, I often find myself wishing Go's type system were a bit better, but the reason I prefer it is because it's fast, easy to reason about, and the tooling/deployment stories are generally awesome (not always though--e.g., package management). So far I'm only nominally familiar with Crystal; I'll have to look into it sometime.

Re: Why the New V8 Is So Damn Fast

#217

Earlier quoted context omitted.

Lots of people believe this but it's false. JVM vs C++ depends very much on the code shapes and what the code is doing. C++ that's very heavy on virtual function calls can be faster written as Java. On the other hand if you use a lot of SIMD intrinsics and things like that, C++ can be a lot faster. W.R.T. AOT vs JIT, as others are pointing out, Graal is a compiler that can execute in both modes, i.e. it's a comparabl…

You make it sound like Java is neck-and-neck with C++ in general. There are definitely cases where naive Java is faster than naive C++, but those cases are infrequent. Java is generally in the ballpark of 1/2 C++ speed alongside Go and C# in the general case. > W.R.T. AOT vs JIT, as others are pointing out, Graal is a compiler that can execute in both modes, i.e. it's a comparable compiler. JITC is about a 20% win fo…

Well, C++ is such a flexible language that it's hard to say what general C++ code looks like. I'd say I'd expect Java to either match or even beat C++ for general "business code" which is pretty vague but is typified by lots of layers of abstraction, lots of data transformation, hash maps, string manipulation etc. Modern compilers like Graal are very good at analyzing and removing abstraction overhead. I'd expect C++ to stomp Java for any sort of numerics work, media codecs, 3D engines, things like that.

my only point was that the JVM specifically isn't faster than AOT languages nor is it faster than AOT Java because of JIT specifically

Hmm, but is there such a thing as an AOT language? You can interpret or JIT compile C and you can interpret, JIT or AOT compile Java too.

I think it's clearly the case that JITC Java is faster than AOT Java. It was maybe unclear for a long time but Graal and SubstrateVM let us compare now. You pay a big performance hit to use a VM-less AOT Java compile. Java is sort of a half-way house between a really dynamic language and a really static language.... it's got dynamic aspects and also static aspects.

Re: Why the New V8 Is So Damn Fast

#218

Earlier quoted context omitted.

> It's a rigid term Ah, neat! I learned something. :) You’re mistaken about only numbers and simple structs being stack allocated. All structs are stack allocated unless they escape, regardless of their contents. Further, arrays and constant-sized slices may also be stack allocated. I’m also pretty sure interfaces are only heap allocated if they escape; in other words, if you put a value in an interface and it doesn’…

Both arrays and interfaces are heap allocated. Slice is just a pointer to a heap allocated array. Structure could be stack allocated, but any of it's fields would not if there is anything but a number. A trivial example: https://segment.com/blog/allocation-efficiency-in-high-perfo... func main() { x := 42 fmt.Println(x) } ./main.go:7: x escapes to heap So a trivial interface cast leads to allocation.

Looks like you're right about interfaces (full benchmark source code: https://gist.github.com/weberc2/87d2fdc379065a2765d1c9f490ad...)!

    BenchmarkEscapeInterface-4        50000000   33.3 ns/op  8 B/op  1 allocs/op
    BenchmarkEscapeConcreteValue-4    200000000  9.45 ns/op  0 B/op  0 allocs/op
    BenchmarkEscapeConcretePointer-4  100000000  10.0 ns/op  0 B/op  0 allocs/op
But arrays are stack allocated:

    BenchmarkEscapeArray-4  50000000   21.3 ns/op  0 B/op  0 allocs/op
And structs are stack allocated, as are their fields--even fields that are structs, slices, and strings!:

    BenchmarkEscapeStruct-4  100000000  12.8 ns/op  0 B/op  0 allocs/op

The code:

    type Inner struct {
    	Slice  []int
    	String string
    	Int    int
    }
    
    type Struct struct {
    	Int    int
    	String string
    	Nested Inner
    }
    
    func (s Struct) AddThings() int {
    	return s.Int + len(s.String) + len(s.Nested.Slice) + len(s.Nested.String) +
    		s.Nested.Int
    }
    
    func BenchmarkEscapeStruct(b *testing.B) {
    	for i := 0; i 

Re: Why the New V8 Is So Damn Fast

#219

Earlier quoted context omitted.

You make it sound like Java is neck-and-neck with C++ in general. There are definitely cases where naive Java is faster than naive C++, but those cases are infrequent. Java is generally in the ballpark of 1/2 C++ speed alongside Go and C# in the general case. > W.R.T. AOT vs JIT, as others are pointing out, Graal is a compiler that can execute in both modes, i.e. it's a comparable compiler. JITC is about a 20% win fo…

Well, C++ is such a flexible language that it's hard to say what general C++ code looks like. I'd say I'd expect Java to either match or even beat C++ for general "business code" which is pretty vague but is typified by lots of layers of abstraction, lots of data transformation, hash maps, string manipulation etc. Modern compilers like Graal are very good at analyzing and removing abstraction overhead. I'd expect C++…

> Hmm, but is there such a thing as an AOT language? You can interpret or JIT compile C and you can interpret, JIT or AOT compile Java too.

You're right that my language was imprecise, but my point stands. JVM does't make Java faster than popular AOT implementations of (for example) Rust or C++ or C, and JVM is almost certainly faster than AOT Java implementations because of decades of optimizations, not because JIT is inherently better than AOT.

> I think it's clearly the case that JITC Java is faster than AOT Java. It was maybe unclear for a long time but Graal and SubstrateVM let us compare now.

Graal is shaping up to be a real game changer, but it's unproven and it's exceptional among JIT implementations. If Graal is all that it's cracked up to be, I wouldn't be surprised if there is a time when all popular JIT implementations perform like Graal, but until such a time, JIT alone doesn't have any clear performance advantages over AOT in general.

Re: Why the New V8 Is So Damn Fast

#220

Earlier quoted context omitted.

Both arrays and interfaces are heap allocated. Slice is just a pointer to a heap allocated array. Structure could be stack allocated, but any of it's fields would not if there is anything but a number. A trivial example: https://segment.com/blog/allocation-efficiency-in-high-perfo... func main() { x := 42 fmt.Println(x) } ./main.go:7: x escapes to heap So a trivial interface cast leads to allocation.

Looks like you're right about interfaces (full benchmark source code: https://gist.github.com/weberc2/87d2fdc379065a2765d1c9f490ad... )! BenchmarkEscapeInterface-4 50000000 33.3 ns/op 8 B/op 1 allocs/op BenchmarkEscapeConcreteValue-4 200000000 9.45 ns/op 0 B/op 0 allocs/op BenchmarkEscapeConcretePointer-4 100000000 10.0 ns/op 0 B/op 0 allocs/op But arrays are stack allocated: BenchmarkEscapeArray-4 50000000 21.3 ns/o…

I'm sure your strings are not stack allocated, they are statically allocated (and would be statically alocated in any language). Not sure about arrays, but dynamic arrays should be dynamically allocated do, your arrays are static probably. They would be heap allocated, if you would use make.
Post reply on HN