Hacker News new | past | comments | ask | show | jobs | submit | more Leszek's comments login

If you do any kind of probing other than linear probing (e.g. quadratic probing) this approach doesn't work anymore, because your collisions are no longer densely grouped together.


A system that tells you the location of (actively flashing) police cars sounds somewhat abusable.


perhaps some signal that is only viewable locally, not globally.

The equivalent of the siren and lights on an emergency vehicle.

Wait...

Oh.


It's a very clear infinite recursion at best, and a buggy definition for odd `n` if that's fixed. I wouldn't imagine making either error if just looping...


With out of order execution, speculation, and SMT, it's hard to say if an instruction stalling means that the CPU can't process something else; CPUs are complex parallel streams of processing and trying to think of them in linear terms necessarily misses some complexity.


Another factor (also mentioned in the article) is dynamic frequency scaling. Is a core at 100% when it's running at it's running 'flat-out' at its nominal frequency or when it has boosted? The boost clock generally depends on thermals, silicon quality and maybe time - so in that case what do you make 100%? If you go for nominal being 100% then sometimes you're going to be at say 120%.


The most obvious answer: 100% is what the manufacturer claims it capable of handling continuously under the worst supported conditions.

The more difficult answer/question is how to communicate that 'full use' value as well as the current use (possibly greater than full) to software which calculates a usage estimate based on various already existing interfaces. Or if yet another interface (standard, if thinking about that XKCD comic) is needed.


I prefer the NASA approach: 100% is whatever as defined in the spec sheet, and any improvements above that are measured in percentages above 100.

As an example, the SSME was nominally operated at 104.5%, and the newer expendable RS-25Es nominally operate at 111%.[1]

So basically: 100% is the CPU running at base frequency, and anything higher (eg: turboing/boosting, overclocking) should result in even higher percentages above 100. This would be a lot more meaningful than whatever "100% CPU load" means today.

[1]: https://en.wikipedia.org/wiki/RS-25#Engine_throttle/output


That's mostly what I stated, though with adjustable frequency products like CPUs and GPUs the question of 'what is the base frequency' is also a question. That's why I carefully phrased around manufacturer's claimed continuous operation in the worst environment supported spec. (Though implicitly with adequate cooling operating, not obviously broken cases like a CPU with it's heat sink shaken off.)


If it could process something else, it would. If it doesn't, it means it can't. So, what are you trying to say?


In the case of SMT (aka hyperthreading) you'd only know if the CPU can process something else by profiling a different thread that's running on the same core.


I like the mental image of this being a very precise matching -- as the sun traces across the sky, the responsibility of on-call passes from desk to desk, town to town, country to country; two engineers on a boat in the Atlantic race to keep up with their rotation...


The logical conclusion is SREpiercer


Same place any other distance-based potential energy (like gravity) comes from: being far away from the magnets -- and on repeated firings of a ball, from pulling it away from the magnets.


To be clear, maybe I was a bit negative, but I was just talking about the technical intro. The rest of the article on not accidentally leaking references through globals and timers, and what tools to use to catch them, is pretty solid.


V8 dev here.

Yes, please avoid leaking memory -- but the intro to this article is incorrect in almost all major points:

> In JavaScript, primitives are assigned/passed by value and not by reference. If you assign a primitive type's value to another variable, the value is copied.

No, primitives are immutable but still passed by reference (that reference is passed by value, which is why assigning to the reference won't change them -- the same is true for objects). Can you imagine if we'd copied strings every time they were passed into a function?

> This also determines how they are stored in memory — primitive values are stored on the stack while objects are stored on the heap, with a reference to their location stored on the stack.

Also no, all primitives except small integers ("Smis") are stored in the heap.

> One important thing to note about variables stored in the stack is that their sizes must be known at compile time. This allows a program to allocate the right amount of memory in the stack. Because the JavaScript engine allocates a fixed amount of memory for primitive values, there is a limit to how large they can be.

Again, no, with strings as the obvious counter example. There's a limit to how large values in general can be, but it's around indexable size and pointer width, not a fixed amount of memory for primitives.

> Memory stored in the heap will live on unless it is explicitly deleted or deallocated.

Is the author confusing the malloc heap with the (garbage collected) JS heap? Sure, V8 has to manage the pages it allocates, but JS authors certainly don't

> To allocate memory in the heap, a program must first scan the heap to find a contiguous memory block large enough to hold the data.

As a sibling comment points out, there are optimisations here with linear allocation buffers that permit bump allocation. Also, don't forget the semi space for young objects, since the GC is generational.


> No, primitives are immutable but still passed by reference

For immutable values the pass-by-reference vs pass-by-value distinction isn't really important. Unless the language provides some way to get the identity of the object there isn't a way to tell a difference.

> Can you imagine if we'd copied strings every time they were passed into a function?

IIUC most Javascript interpreters optimize copying strings anyways, so this wouldn't be a big deal. For example even though `s.slice(1)` is a "copy" most engines (I believe V8 included) will use the same backing string for both. So the difference would be a pointer on the stack vs a pointer+length on the stack and copying an extra word is not a huge difference.

But maybe this is just being nitpicky, since the article is focused on performance the lower level details do mater not the semantics. However for strings I don't think the difference between their model and reality is very significant.


You're talking about semantics and you're totally right, there's plenty of cases in the implementation where things are not copied when they should be (string slices) or copied when they shouldn't be (boxed double writes into mutable double boxes). As you say though, the semantics are kind of irrelevant when you're talking about actual memory behaviour of allocations.

There's actually lots of really interesting consequences of the current implementation, and the various tricks it does around what's observable and what's fast, it's just not what's described here.


> For example even though `s.slice(1)` is a "copy" most engines (I believe V8 included) will use the same backing string for both.

That’s not a copy, it skips the first character!


It's semantically a copy of most of the string.


Nothing against the author, but damn is this a good example of why you can't just trust every piece of technical writing you see.


Maybe strings are not considered primitives by the author. They do give a list of "Data types stored in the stack" which I understood to be the "primitives" in what follows.


From the article, "Data types stored in the stack include: [...] string"


Ouch. Yeah that's wrong.


only SMIs are passed by value (because they are actually encoded in the reference data type)

It might be a bit outdated but here's more https://github.com/thlorenz/v8-perf

Also the https://v8.dev/ blog is awesome.


You're looking at Oilpan, which is the C++ GC for Blink, not the one for V8.

But, the V8 one is very similar in many respects (the same team works on both), including linear allocation buffers.


They are one and the same I as I understand it now:

https://v8.dev/blog/oilpan-library https://github.com/v8/v8/blob/main/include/cppgc/README.md

Quote for the frist article:

> We launched the library [Oilpan] in V8 v9.4 and enabled it in Blink starting in Chromium M94.


It's a bit confusing, I agree -- Oilpan is part of the V8 sources for shipping-the-org-chart reasons, but it isn't actually the GC used by V8 itself for JavaScript objects and the JS heap, it's the GC used by Blink for DOM objects etc.

The biggest difference between the two is that JS objects are fully managed by the GC and V8 has full control over their layout and access (e.g. they are accessed via explicit pointer + field offset in the runtime), while Oilpan works on C++ objects; there's a billion consequences of this, in particular that JS objects are movable (because we can safely update pointers) and Oilpan objects aren't (because C++ can do pretty much whatever it wants).


At one point, it was supposed to be the universal GC for chrome. In fact, that was cited as the major holdup for getting the DartVM into chrome, they wanted a unified GC between dart, v8, and the DOM.


Thanks for clarifying!


Browsers do a fast partial parse to figure out things like scoping and variable names, but skip actually building an AST so it's still a lot quicker than full parsing (e.g. https://v8.dev/blog/preparser)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: