1

I am aware that JavaScript is a garbage collected language but I don't really mind freeing memory ahead of GC sweeps if it means less pressure on the GC and my application can run a little smoother/more consistently (particularly on low end devices).

I know in C we have free(), is there something similar in JavaScript?

I know this is invalid but is there something simple like:

const myObj = {}
let myText = "Hello World"

delete myObj
delete myText

// Or 
myObj.free()
myText.free()

Where JavaScript knows how to teardown the data

David Alsh
  • 6,747
  • 6
  • 34
  • 60
  • Some objects will allocate some memory that you can then "free", e.g ArrayBuffers. But for your case it seems that you'd be more interested in something like [WeakRef](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef), which doesn't really allow you to manually free them, but rather will not hold the object from being GCed. – Kaiido Sep 25 '21 at 02:58
  • Does this answer your question? [Can I trigger JavaScript's garbage collection?](https://stackoverflow.com/questions/8032928/can-i-trigger-javascripts-garbage-collection) – kmoser Sep 25 '21 at 03:15
  • The question is more about freeing specific variable declarations, not running a complete GC sweep. It's more of a micro application-level optimisation rather than anything else. – David Alsh Sep 25 '21 at 03:34

1 Answers1

4

No, there is no manual memory management in JavaScript, just automatic garbage collection. JavaScript was originally designed for use in browsers; if a random webpage could choose to allocate memory in such a way that the garbage collector would never reclaim it without manual intervention, that's basically asking for memory leaks (unintentional or malicious denial of service by the web page).

Similarly, allowing manual frees would also allow you to intentionally corrupt memory or trigger segfaults; for the simplest example, imagine:

var a = {...define object here...};
var b = a;
JSfree(a);
b.literally_anything_i_do_is_going_to_do_something_horrible();

This isn't a reference counted language (not on any modern JS implementation), and the object tree is one way; a and b know about the object they share, but the object has no idea that it's aliased to two names. So when you forcibly free it through one alias, there's no way for the other alias to know it's now a dangling reference. Giving this sort of power to a random webpage is even worse than allowing manual allocation without GC tracking (which is basically just denial of service), because this is the sort of bug that can allow arbitrary reads and writes into process memory (once you've freed it, other stuff can get allocated there, and that dangling reference is the hacker's "in" to start taking over), eventually leading to breaking the browser sandbox and attacking the local OS.

In short: No, you can't do manual memory management, for very good reasons (yes, technically node.js could provide add-ons to JS to allow it since it's not subject to the same risks as web browsers; it does not, because the benefits aren't worth the cost of building and maintaining such a capability for only the most niche of use cases).

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • 1
    Why would a manual "free" be incompatible with the automatic GC? – Kaiido Sep 25 '21 at 02:54
  • Sorry I was looking for manual deallocation, not allocation; where you can clean up ahead of the GC, leaving the normal GC sweeps to pick up memory you haven't already freed – David Alsh Sep 25 '21 at 02:55
  • @Kaiido: Because you can't know when a free would be safe. `var a = {...someobjectdefinition...};` then later you do `var b = a;`. The object itself doesn't know it's aliased to both `a` and `b`, so if you manually "free" through one, the other ends up with a dangling reference. You can always reassign to `null`/`undefined` to free up a *reference* immediately, but a mark-sweep garbage collector can't actually use that information to immediately free the *object* until it actually does a traversal to be sure no other roots reference that object. You haven't saved the GC meaningful work. – ShadowRanger Sep 25 '21 at 03:01
  • @DavidAlsh: See my response to Kaiido; anything you could do to force a free would also allow you to create dangling references that could lead to segfaults or heap corruption if used (say, when the GC tries to traverse the dangling reference to mark it as visited). – ShadowRanger Sep 25 '21 at 03:02
  • Oh you're absolutely right – David Alsh Sep 25 '21 at 03:04
  • @Kaiido: Also, to be clear, my answer was written when the question asked about manual memory management in general, not deallocation specifically. – ShadowRanger Sep 25 '21 at 03:04
  • We could very well have an API to force the GC to kick in, browsers actually already expose it in their dev-tools API. Objects that are still referenced would not get collected, and you could use WeakRefs to have objects collected as soon as you want, without a risk of "dangling reference". – Kaiido Sep 25 '21 at 03:06
  • @Kaiido: That's hugely different from "can manually deallocate a specific given object cheaply". The whole point here was to save the garbage collector work and run more smoothly; adding extra GC runs is the *opposite* of that. They likely don't provide that capability precisely because *no one* can be trusted to use it appropriately; almost every manually initiated GC is a bad idea even in languages that allow it like Java, and allowing a webpage to cause constant GCs on-demand "for optimization"? Terrible idea. I know too many web developers to trust even 5% of them with such a tool. – ShadowRanger Sep 25 '21 at 03:17
  • @Kaiido: For more information, see [When is it a good idea to force garbage collection?](https://softwareengineering.stackexchange.com/q/276585/215049) (Spoiler: The answer is "Never") – ShadowRanger Sep 25 '21 at 03:19