How to imitate garbage collection in javascript? - javascript

Let's say I have a library that keeps an array of objects, the purpose is not really relevant to the issue. it looks like this:
window.Tracker = {
objects: [],
track: function(obj){
this.objects.push(obj)
}
}
In other parts of the app, Vue/React components constantly push objects to this library as they're loaded from a server:
this.movie = { id: 56456, name: "Avengers" }
Tracker.track(this.props.movie)
Overtime, the Tracker.objects array gets bigger and bigger, mostly because of objects no longer needed (their components no longer exist), and I really don't want to keep objects like this in the array.
The problem is I don't have control over anything aside from this Tracker library. (so I can't really make callbacks when the object is no longer needed)
But I need a way to garbage collect/ get rid of objects that are no longer used by anything other than in the Tracker.objects array.
Is this possible?

The only way to store objects in a collection so that they are still garbage collected are WeakMaps. However you can't iterate them:
Because of references being weak, WeakMap keys are not enumerable (i.e. there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism.
~ MDN
So no, this is not possible in js for good reasons.

Related

finding all keys that map to a value in javascript. And efficient alternatives

I'm working on an application in javascript where each user is in a room. No two users share the same name and no two rooms share the same name. Currently I have it set up like this:
var userroommap = {
username: "room",
username2: "room",
username3: "room2"
}
getting the room a user is in is as simple as
userroommap["user"]
but in order to get all users which are present in a room I would have to iterate over the entire userroommap like so:
for (var x in userroommap) {
if (userroommap[x] == "room")
//user x is present in room
}
}
In my application I must know which users are in which rooms very often so I am considering using another object to hold all users in a room, something like:
var roomusermap = {
room:["username", "username2"],
room2:["username3"]
}
Adding users to the room is trivial because all you have to do is append to an array, however removing a username from a room requires iterating over the array and becomes a decent operation. This already is a decent solution to my problem, but I became curious if there was a better solution. So: is there a better way to (i) store the roomusermap, perhaps without arrays? or, alternatively (ii) find all users in a room?
The data-structure described in the previous answer is called a BiMap.
A BiMap ideally provides equivalent performance for value: keys lookup operations as for key: values lookups. It is typically implemented by internally managing two separate maps (one with a forward-mapping {key:values} and one with a reverse-mapping {value:keys}).
Here's an existing implementation to use if you're not rolling your own. https://www.npmjs.com/package/bimap
Unless you've identified a genuine, real-world performance problem, I'd stick with the simple solution.
That said, a few thoughts for you:
All modern JavaScript engines give you the Object.keys function, which returns an array of an object's own enumerable properties. This may be more efficient than your for-in loop for two reasons:
It's happening within the engine's code, which lets the engine optimize
for-in looks for enumerable properties in prototype objects, whereas Object.keys knows it's only supposed to look in that specific object
Your roomusermap can contain maps per room, it doesn't need to use arrays.
var roomusermap = {
room: {
username: user,
username2: user2
},
room2: {
username3: user3
}
};
Adding a user to a room becomes:
userroommap[username] = roomname;
roomusermap[roomname][username] = user;
Removing a user is:
delete userroommap[username];
delete roomusermap[roomname][username];
If you're seeing performance problems with those map objects, something to keep in mind is that removing a property from an object (delete) puts the object into "dictionary mode" on several JavaScript engines (having previously been in a more optimized state), significantly impacting the time required to look up properties on that object.
So in the very hypothetical case where the property lookup performance starts to be an issue, you could consider storing undefined rather than deleting the property. E.g., instead of:
delete userroommap[username];
delete roomusermap[roomname][username];
you'd do
userroommap[username] = undefined;
roomusermap[roomname][username] = undefined;
However, you'd have to adjust your checks for whether a user is in a room, and you couldn't use Object.keys (on its own) to get the list anymore since you have to weed out the properties with the value undefined. You could use Object.keys with filter:
var map = roomusermap[roomname];
var users = Object.keys(map).filter(function(username) {
return map[username] !== undefined;
});
So you'd really want to do that only if you've identifed a genuine problem caused by objects going into dictionary mode.

What is the accepted convention for when to use an object containing objects vs an array of objects in JSON?

I am currently in the process of writing a GUI which fundamentally allows users to edit/populate/delete a number of settings files, where the settings are stored in JSON, using AJAX.
I have limited experience with JavaScript (I have little experience with anything beyond MATLAB to be frank), however I find myself restructuring my settings structure because of the semantics of working with an object containing more objects, rather than an array of objects. In C# I would do this using a KeyValuePair, however the JSON structure prevents me from doing what I'd really like to do here, and I was wondering whether there was an accepted convention for do this in JavaScript which I should adopt now, rather than making these changes and finding that I cause more issues than I solve.
The sample data structure, which has similar requirements to many of my structures, accepts any number of years, and within these any number of events, and within these a set number of values.
Here is the previous structure:
{"2013":
{
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...},
...}
Here is my ideal structure, where the year/event name operates as a key of type string for a value of type Array:
["2013":
[
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...],
...]
As far as I am aware, this would be invalid JSON notation, so here is my proposed structure:
[{"Key":"2013",
"Value":
[{"Key":"someEventName",
"Value":
{
"data1":"foo",
"data2":"bar",
...}
},
...]
},
...]
My proposed "test" for whether something should be an object containing objects or an array of objects is "does my sub-structure take a fixed, known number of objects?" If yes, design as object containing objects; if no, design as array of objects.
I am required to filter through this structure frequently to find data/values, and I don't envisage ever exploiting the index functionality that using an array brings, however pushing and removing data from an array is much more flexible than to an object and it feels like using an object containing objects deviates from the class model of OOP; on the other hand, the methods for finding my data by "Key" all seem simpler if it is an object containing objects, and I don't envisage myself using Prototype methods on these objects anyway so who cares about breaking OOP.
Response 1
In the previous structure to add a year, for example, the code would be OBJ["2014"]={}; in the new structure it would be OBJ.push({"Key":"2014", "Value":{}}); both of these solutions are similarly lacking in their complexity.
Deleting is similarly trivial in both cases.
However, if I want to manipulate the value of an event, say, using a function, if I pass a pointer to that object to the function and try to superceed the whole object in the reference, it won't work: I am forced to copy the original event (using jQuery or worse) and reinsert it at the parent level. With a "Value" attribute, I can overwrite the whole value element however I like, provided I pass the entire {"Key":"", "Value":""} object to the function. It's an awful lot cleaner in this situation for me to use the array of objects method.
I am also basing this change to arrays on the wealth of other responses on stackoverflow which encourage the use of them instead of objects.
If all you're going to do is iterate over your objects, then an array of objects makes more sense. If these are settings and people are going to need to look up a specific one then the original object notation is better. the original allows people write code like
var foo = settings['2013'][someEventName].data1
whereas getting that data out of the array of objects would requires iterating through them to find the one with the key: 2013 which depending on the length of the list will cause performance issues.
Pushing new data to the object is as simple as
settings['2014'] = {...}
and deleting data from an object is also simple
delete settings['2014']

FRP complex state - immutability vs performance

My question is about mutability of 'state machine' object in FRP. I'm evaluating Bacon.js's Observable.withStateMachine.
My domain is trading robots. I've got a source event stream of 'Orders' which actually are tuples (buy or sell,price,volume)
I want to use something like the following pseudocode
```
orders.withStateMachine(new Book(), function(book,order) { // is 'book' mutable ?!!
var bookModifiedEvents = book.merge(order);
return [book, modifications];
})
Book.prototype.merge = function(order) {
// either append order into the Book, or generate Trade when order gets filled.
// generate corresponding bookModifiedEvents and tradeEvents.
return bookModifiedEvents.merge(tradeEvents);
}
```
This code shoud aggregate exchange orders into order book (which is a pair of priorityqueues for bids and asks orders sorted by price) and publish 'bookModified' and 'tradeOccured' event streams.
What I don't quite understand: Can I directly modify initial state object that was passed to my callback I give to .withStateMachine method?
Since FRP is all about immutability, I think I shouldn't. In such case I should create a lot of orderbook objects, which are very heavy (thousands of orders inside).
So I began to look to immutable collections, but, first, there is no immutable priority queue (if it makes sense), and, second, I'm afraid the performance would be poor for such collections.
So, finalizing, my question has 2 parts:
1) In case of HEAVY STATE, is it LEGAL to modify state in .withStateMachine??
Will it have some very-very bad side effects in bacon.js internals?
2) And if it is NOT allowed, what is recommended? Immutable collections using tries? Or some huge refactoring so I will not need orderbooks as phenomena in my code at all?
Thanks.
The whole idea of reactive programming doesn't work, if you mutate data or cause side-effects in something which is expected to be referentially transparent.
So 1) modifying the state isn't illegal, but you can run into undefined behaviour scenarios. So you are on your own.
2) And as mutation isn't recommended, what is an alternative: Try immutable.js as you mentioned it, make priority queue build on top of List or whatever is more suitable. Don't prejudge the performance. Immutable collections use sharing, so when you copy a collection, you don't need to copy the elements as they could be shared (they are assumed to be immutable too - why to copy stuff we aren't changing).

Worse framerate with Object Pool

I am working on a game. And I have now read a couple of articles suggesting I should be re-using objects instead of creating new ones to reduce the frame drop when Garbage Collection sweeps in and removes objects.
Articles read on the subject:
High-Performance, Garbage-Collector-Friendly Code
Object Pools
Static Memory Javascript with Object Pools
However I am not getting the results that I want. Using an Object Pool is giving me worse framerates than just creating and destroying objects.
The one good news - besides learning - that I got out of this was that the tests not using Object Pools occasionally became unresponsive and crashed.
Why is that?
And how come I am not getting similar results as the people in those blogs?
Test 1 - *Using Arrays to hold the objects. Keeping reference by moving them in between two arrays.
Using for loop to remove objects from array
Using indexOf to remove objects from array
Test 2 - Using an Array to hold the objects. Not keeping references.
OCCASIONALLY CRASHES THE BROWSER:
Using for loop to remove objects from array
Using indexOf to remove objects from array
Test 3
Using Objects instead of Arrays to hold the objects. Keeping References.
Test 4
OCCASIONALLY CRASHES THE BROWSER:
Using an Object instead of an Array to hold the objects. Not keeping references.
Please Edit if you think this can be improved.
Oh boy! I did it. Now I can answer my own question!
I read this article:
How to write low garbage real-time Javascript
And it finally said click.
All my previous code examples are using Array.prototype.pop() and Array.prototype.slice()
Both of those return objects. So I was still creating a lot of garbage.
Instead I realized I could just use one Array and move Objects around - never having to remove anything.
I extended the array object with a property: .activeLength and I was a happy camper.
"Removal" of objects:
function removeObject (object, pool) {
var tempObj;
for (var i = 0; i < pool.length; i++) {
if ( pool[i] === object ) {
pool.activeLength --;
canvas.scene.remove( pool[i] );
tempObj = pool[i];
pool[pool[i]] = pool[pool.length - 1];
return;
}
}
}
I'm only moving objects around. And so I am not creating any garbage here. (Three.js might though, since I am creating 3D objects with the Three.js Library);
Object Pool ~without~ Garbage

JavaScript Performance and Memory Access

EDIT
Did a JSPerf. Ran it against Chrome as Chrome uses v8.
http://jsperf.com/passing-large-objects
It looks like passing a large object doesn't matter; the difference is negligible. However, lookup on an object at some point gets a lot slower.
INTRODUCTION:
I’m writing a 2D JavaScript game engine while following component based and data oriented (via typed arrays) design principles. It’s designed for use by a simulation based multiplayer netcode.
My performance concerns are for the master simulation that will be running on the server; I believe that client browsers will be more than fast enough. As of now, the server is NodeJS, so it would involve the V8 interpreter. However, I’m not ruling out a switch to other technologies like Vert.x, which I believe uses the Rhino interpreter.
THE QUESTION:
When does JavaScript access objects in memory?
More specifically, let’s say I have an object like so.
var data = {
a1 : new Float64Array(123456),
a2 : new Float64Array(123456),
…
a9001: new Float64Array(123456)
};
And now let’s say I pass it to this function like so.
var update = function(obj) {
for(var property in obj) {
if(obj.hasOwnProperty(property)) {
obj[property][0]++;
}
}
};
update(data);
At what point are the Float64 arrays accessed? Does it access it the moment I pass data into update, attempting to load all 9001 arrays into the memory cache and page faulting like crazy? Does it wait to load the arrays until the hasOwnProperty? Or obj[property]? Or obj[property][0]?
WHY I ASK:
I’m trying to follow the data oriented design principles of keeping stuff in contiguous blocks of memory. Depending on how JavaScript works with memory, I will have to change the interface and structure of the engine.
For example, if all the arrays in data are accessed the moment I pass it into update, then I have to make special data objects with as few arrays as possible to reduce page faulting. If however the arrays are only accessed at say obj[property], then I can pass a large data object with more arrays without any performance penalties, which simplifies a lot of things.
A big reason why I’m not sure of the answer is because JavaScript objects aren’t objects like in other languages. From some random reading here or there, I’ve heard stuff like JavaScript objects have their own internal class. I’ve also heard of things like JavaScript objects being hash tables so you incur a lookup time with every property that you access.
Then I’ve heard that the interpreters treat objects differently based on how large the object is; smaller ones are treated one way and larger ones another. So jsperf stuff may not be an accurate measure.
FURTHER:
Taking the example further, there’s the question of how JavaScript handles nested objects. For example:
var properties = {
a1 : {
a1 : {
…
a1 : {
}
}
},
a2 : {
a2 : {
…
a2 : {
}
}
},
…
a9001 : {
a9001 : {
…
a9001 : {
}
}
}
};
var doSomething = function() {
};
doSomething(properties);
If passing in properties to doSomething causes every sub object and their sub objects to get accessed, then that’s a performance hit. If however it just passes a reference to the properties object and only accesses the sub objects when the code calls them, then it’s not bad at all.
If I had access to Vectors, I’d make an entity system framework in a heartbeat and this wouldn’t really be a problem. If I had access to pointers, which I believe only accesses the object when the code converts the pointer, then I could try other things. But only having typed arrays at my disposal limits my options, so I end up agonizing over questions like this.
Thanks for the any insight you can provide. I really appreciate it.

Categories

Resources