Memory storage of a javascript array - javascript

Just a simple question, but can't get an answer on my own.
In memory Array are use contiguous space to store the data.
Object use pointer to look where the data are stored.
(correct me if i'm wrong :D )
In Javascript Array are object, does it means that Array work like object for memory storage ?

Since you can't get references to actual memory locations in Javascript, what difference does it make *how the memory is allocated? In Javascript, everything is an Object because there isn't even a type for anything (really)... var foo = 5; foo = "hello"; foo = function(){}; and so on and so forth. All you need to know is how an Array works in javascript. Don't worry about how it's storing its values and where... that's not something you have any control over and it makes absolutely no difference.

Related

WeakSet: garbage collection doesn't work? [duplicate]

The WeakSet is supposed to store elements by weak reference. That is, if an object is not referenced by anything else, it should be cleaned from the WeakSet.
I have written the following test:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset);
numbers = undefined;
console.log(weakset);
Even though my [1, 2, 3] array is not referenced by anything, it's not being removed from the WeakSet. The console prints:
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
Why is that?
Plus, I have one more question. What is the point of adding objects to WeakSets directly, like this:
weakset.add({name: "Charlie"});
Are those Traceur's glitches or am I missing something?
And finally, what is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
it's not being removed from the WeakSet. Why is that?
Most likely because the garbage collector has not yet run. However, you say you are using Traceur, so it just might be that they're not properly supported. I wonder how the console can show the contents of a WeakSet anyway.
What is the point of adding objects to WeakSets directly?
There is absolutely no point of adding object literals to WeakSets.
What is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
All you can get is one bit of information: Is the object (or generically, value) contained in the set?
This can be useful in situations where you want to "tag" objects without actually mutating them (setting a property on them). Lots of algorithms contain some sort of "if x was already seen" condition (a JSON.stringify cycle detection might be a good example), and when you work with user-provided values the use of a Set/WeakSet would be advisable. The advantage of a WeakSet here is that its contents can be garbage-collected while your algorithm is still running, so it helps to reduce memory consumption (or even prevents leaks) when you are dealing with lots of data that is lazily (possibly even asynchronously) produced.
This is a really hard question. To be completely honest I had no idea in the context of JavaScript so I asked in esdiscuss and got a convincing answer from Domenic.
WeakSets are useful for security and validation reasons. If you want to be able to isolate a piece of JavaScript. They allow you to tag an object to indicate it belongs to a special set of object.
Let's say I have a class ApiRequest:
class ApiRequest {
constructor() {
// bring object to a consistent state, use platform code you have no direct access to
}
makeRequest() {
// do work
}
}
Now, I'm writing a JavaScript platform - my platform allows you to run JavaScript to make calls - to make those calls you need a ApiRequest - I only want you to make ApiRequests with the objects I give you so you can't bypass any constraints I have in place.
However, at the moment nothing is stopping you from doing:
ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super
And so on, note that you can't keep a normal list or array of ApiRequest objects since that would prevent them from being garbage collected. Other than a closure, anything can be achieved with public methods like Object.getOwnPropertyNames or Object.getOwnSymbols. So you one up me and do:
const requests = new WeakSet();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
}
Now, no matter what I do - I must hold a valid ApiRequest object to call the makeRequest method on it. This is impossible without a WeakMap/WeakSet.
So in short - WeakMaps are useful for writing platforms in JavaScript. Normally this sort of validation is done on the C++ side but adding these features will enable moving and making things in JavaScript.
(Of course, everything a WeakSet does a WeakMap that maps values to true can also do, but that's true for any map/set construct)
(Like Bergi's answer suggests, there is never a reason to add an object literal directly to a WeakMap or a WeakSet)
By definition, WeakSet has only three key functionalities
Weakly link an object into the set
Remove a link to an object from the set
Check if an object has already been linked to the set
Sounds more pretty familiar?
In some application, developers may need to implement a quick way to iterate through a series of data which is polluted by lots and lots of redundancy but you want to pick only ones which have not been processed before (unique). WeakSet could help you. See an example below:
var processedBag = new WeakSet();
var nextObject = getNext();
while (nextObject !== null){
// Check if already processed this similar object?
if (!processedBag.has(nextObject)){
// If not, process it and memorize
process(nextObject);
processedBag.add(nextObject);
}
nextObject = getNext();
}
One of the best data structure for application above is Bloom filter which is very good for a massive data size. However, you can apply the use of WeakSet for this purpose as well.
A "weak" set or map is useful when you need to keep an arbitrary collection of things but you don't want their presence in the collection from preventing those things from being garbage-collected if memory gets tight. (If garbage collection does occur, the "reaped" objects will silently disappear from the collection, so you can actually tell if they're gone.)
They are excellent, for example, for use as a look-aside cache: "have I already retrieved this record, recently?" Each time you retrieve something, put it into the map, knowing that the JavaScript garbage collector will be the one responsible for "trimming the list" for you, and that it will automatically do so in response to prevailing memory conditions (which you can't reasonably anticipate).
The only drawback is that these types are not "enumerable." You can't iterate over a list of entries – probably because this would likely "touch" those entries and so defeat the purpose. But, that's a small price to pay (and you could, if need be, "code around it").
WeakSet is a simplification of WeakMap for where your value is always going to be boolean true. It allows you to tag JavaScript objects so to only do something with them once or to maintain their state in respect to a certain process. In theory as it doesn't need to hold a value it should use a little less memory and perform slightly faster than WeakMap.
var [touch, untouch] = (() => {
var seen = new WeakSet();
return [
value => seen.has(value)) || (seen.add(value), !1),
value => !seen.has(value) || (seen.delete(value), !1)
];
})();
function convert(object) {
if(touch(object)) return;
extend(object, yunoprototype); // Made up.
};
function unconvert(object) {
if(untouch(object)) return;
del_props(object, Object.keys(yunoprototype)); // Never do this IRL.
};
Your console was probably incorrectly showing the contents due to the fact that the garbage collection did not take place yet. Therefore since the object wasn't garbage collected it would show the object still in weakset.
If you really want to see if a weakset still has a reference to a certain object then use the WeakSet.prototype.has() method. This method, as the name implies returns a boolean indicating wether the object still exists in the weakset.
Example:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset.has(numbers));
numbers = undefined;
console.log(weakset.has(numbers));
Let me answer the first part, and try to avoid confusing you further.
The garbage collection of dereferenced objects is not observable! It would be a paradox, because you need an object reference to check if it exists in a map. But don't trust me on this, trust Kyle Simpson:
https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch5.md#weakmaps
The problem with a lot of explanations I see here, is that they re-reference a variable to another object, or assign it a primitive value, and then check if the WeakMap contains that object or value as a key. Of course it doesn't! It never had that object/value as a key!
So the final piece to this puzzle: why does inspecting the WeakMap in a console still show all those objects there, even after you've removed all of your references to those objects? Because the console itself keeps persistent references to those Objects, for the purpose of being able to list all the keys in the WeakMap, because that is something that the WeakMap itself cannot do.
While I'm searching about use cases of Weakset I found these points:
"The WeakSet is weak, meaning references to objects in a WeakSet are held weakly.
If no other references to an object stored in the WeakSet exist, those objects can be garbage collected."
##################################
They are black boxes: we only get any data out of a WeakSet if we have both the WeakSet and a value.
##################################
Use Cases:
1 - to avoid bugs
2 - it can be very useful in general to avoid any object to be visited/setup twice
Refrence: https://esdiscuss.org/topic/actual-weakset-use-cases
3 - The contents of a WeakSet can be garbage collected.
4 - Possibility of lowering memory utilization.
Refrence: https://www.geeksforgeeks.org/what-is-the-use-of-a-weakset-object-in-javascript/
##################################
Example on Weakset: https://exploringjs.com/impatient-js/ch_weaksets.html
I Advice you to learn more about weak concept in JS: https://blog.logrocket.com/weakmap-weakset-understanding-javascript-weak-references/

JavaScript optimizations: how to cache local variables' initial values more efficiently?

I'm just curious. Maybe someone knows what JavaScript engines can optimize in 2013 and what they can't? Any assumptions for nearest future? I was looking for some good articles, but still there is no "bible" in the internet.
Ok, let's focus on single quesiton:
Suppose I have a function which is called every 10ms or in a tight loop:
function bottleneck () {
var str = 'Some string',
arr = [1,2,3,4],
job = function () {
// do something;
};
// Do something;
// console.log(Date.getTime());
}
I do not need to calculate the initial values for variables every time, as you see. But, if I move them to upper scope, I will loose on variable lookup. So is there a way to tell Javasript engine to do such an obvious thing - precalculate variables' initial values?
I've careated a jsperf to clear my question. I'm experimenting with different types. I'm especially interested in functions and primitives.
if you need to call a function every 10ms, and it's a bottleneck, the first thought you should have is "I shouldn't call this function every 10ms". Something went wrong in the architecting you did. That said, see 1b in http://jsperf.com/variables-caching/2, which is about four times faster than your "cached" version - the main reason being that for every variable in your code, you're either moving up scope, or redeclaring. In 1b, we go up scope once, to get "initials", then set up local aliasses for its content, from local reference. Much time is saved.
(Concerns V8)
Well the array data itself is not created but an unique array object needs to be created every-time. The backing array for the values 1,2,3,4 is shared by these objects.
The string is interned and it is actually fastest to copy paste same string everywhere as a literal rather than referencing some common variable. But for maintenance you don't really want to do that.
Don't create any new function inside a hot function, if your job function references any variables from the bottleneck function then first of all those variables will become context allocated and slow to access anywhere even in the outer function and it will prevent inlining of the bottleneck function as of now. Inlining is a big deal optimization you don't want to miss when otherwise possible.

Do javascript objects inside of an array erase from the memory when I clear the array?

I never really gave much thought to garbage collection and I don't know whether or not it is necessary to take into account when making small javascript games/applications. Any advice is appreciated, but I will ask my specific question at the end.
A lot of the time I write code of this form:
var foos=new Array();
generateFoos();
function generateFoos()
{
foos=[];
for (fooIndex=0;fooIndex<numberOfFoos;fooIndex++)
{
foos[fooIndex]=new foo(Math.random(),Math.random());
}
}
function foo(bar,bas)
{
this.bar=bar;
this.bas=bas;
}
So my question is, when I say foos=[] (line 5), does this delete the objects in that array from the memory or do they float around somewhere, making the program larger and slower? What should I do if I want to call generateFoos() a loooot of times, like every time the user presses a key.
Thanks!
For a specific answer, since the accepted one doesn't actually answer the question directly, is that yes, foo = [] does de-reference any previous values in the array.
As Ales says, "An object becomes eligible for garbage collection when it becomes unreachable." Indeed, this is when the browser will clear such things from memory.
An important point, delete DOES NOT GARBAGE COLLECT.
You see this over and over, and even in the comments on this question. The delete keyword removes a property from an object and has nothing to do with garbage collection.
I also wanted to offer some advice on your code itself.
1) Use literals, not new, for basic data types
2) Don't call functions before you declare them. Yes, it works but its messy and harder to read later. Remember, you spend much more time reading your code than writing it. Make it easy to follow later.
3) Remember your function scope. Any variable declared without var goes global. With var, it remains within the scope of the function that contains it. Another way variables are scoped within a function is when they are passed in as named parameters.
4) Use var on your functions when creating them. In your code, your functions are globals.
5) Use spacing. Density of text is not next to godliness. You might be 20-something now with great eyesight, but you'll appreciate white space in just a very few short years.
6) Declare counters in for loops with var. Unless you want them to be global. And you almost never will.
Lets re-work your code now:
var numberOfFoos = 10,
foos = [];
var generateFoos = function(){
foos = [];
for( var fooIndex = 0; fooIndex < numberOfFoos; fooIndex++ ){
foos[ fooIndex ] = new foo( Math.random(), Math.random() );
}
},
foo = function( bar, bas ){
this.bar = bar;
this.bas = bas;
}
generateFoos();
console.log( foos );
To answer your question : An object becomes eligible for garbage collection when it becomes unreachable. If your program is not holding any other references to the objects in that array, they will be garbage collected.
The timing of the actual garbage collection depends on many aspects and on the choosen Garbage Collection algorithm but you should not worry about it when writing your code.
The best advice when considering Garbage collection is to leave the Garbage collector to do its job. Do not try to instruct it or help it (by e.g. nulling references manually). Focus on the problem and functional aspect of the code.

JavaScript linking two objects

What is a memory efficient way to link two objects? If you store objects using two arrays with corresponding index values the object won't be released from memory.
The implementation should look like the following.
var obj ={};
var linkedobj = getLinkedObject(obj);
var obj2 ={}
var linkedobj2 = getLinkedObject(obj2);
Objects are general containers
If all you want to do is associate one object with another one, then why not have them point to one another?
var obj = {};
var obj2 = {};
obj.linkedObject = obj2;
obj2.linkedObject = obj;
This would a normal thing to do, and doesn't have bad implications on memory.
Releasing memory
If you are asking about holding a table full of object references, you are correct that the object will not disappear until all of the live references to it are gone. Javascript has a garbage collector, and as long as your table or array has a good reference, it will be backed by memory for you. If you give an object to a table and then want it to be deleted from memory entirely, you can simply remove it from your table also. You could also just remove the table, assuming it doesn't need to hold anything else.
If you are determined to have a getLinkedObject function return an object for another object, you can still allow the objects to each hold the associate reference.
function getLinkedObject(anObject) {
return anObject.linkedObject;
}
This would probably be accompanied by a counterpart:
function linkObjects(anObject, anotherObject) {
anObject.linkedObject = anotherObject;
anotherObject.linkedObject = anObject;
}
Doing this allows you to worry a little less about memory management, which in Javascript (a high-level, dynamic environment with a garbage collector) is typically appropriate.
Unless you use keparo's answer, which from your follow-up comment sounds like not an option, what you're asking for is basically impossible. Because, since you can't augment the original object, you need some method of storing a reference to it. But (since JavaScript has no concept of weak references) this will always prevent it from being garbage collected, contradicting your requirements statement.

workaround: javascript dictionary which takes objects as keys

I read a few questions and answers about javascript dictionary implementations, but they don't meet my requirements:
the dictionary must be able to take objects as keys
the values must be accessible by the []-operator
So I came up with the idea to overwrite the valueOf-method in Object.prototype, as follows:
Object.__id__ = 0;
Object.prototype.valueOf = function() {
if(!this.__id__)
this.__id__ = ++Object.__id__;
return "__id__" + this.__id__;
}
Object.prototype.toString = Object.prototype.valueOf;
//test
var x = {p1: "5"};
var y = [6];
var z = {};
z[x] = "7";
z[y] = "8";
console.log(z[x], z[y]);
I tested this with google-chrome and it seems to work well, but I'm a bit sceptical, whether this will cause some drawbacks, since it was so easy to implement.
Considering that the valueOf method is not used for other purposes in the whole code, do you think there are any disadvantages?
It's an interesting idea. I suggest my jshashtable. It meets your first requirement but not the second. I don't really see the advantage of insisting on using the square bracket property access notation: do you have a particular requirement for it?
With jshashtable, you can provide a hashing function to the Hashtable constructor. This function is passed an object to be used as a key and must return a string; you could use a function not dissimilar to what you have there, without having to touch Object.prototype.
There are some disadvantages to your idea:
Your valueOf method will show up in a for...in loop over any native object;
You have no way determining which keys should be considered equal, which is something you may want to do. Instead, all keys will be considered unique.
This won't work with host objects (i.e. objects provided by the environment, such as DOM elements)
It is an interesting question, because I had so far assumed that any object can be used as an index (but never tried with associative arrays). I don't know enough about the inner workings of JavaScript to be sure, but I'd bet that valueOf is used somewhere else by JavaScript, even if not in your code. You might run into seemingly inexplicable problems later. At least, I'd restrict myself to a new class and leave Object alone ;) Or, you explicitly call your hashing function, calling it myHash() or whatever and calling z[x.myHash()] which adds clutter but would let me, personally, sleep better ;) I can't resist thinking there's a more JavaScript-aware solution to this, so consider all of these ugly workarounds ;)
If you came upon this question looking for a JS dictionary where objects are keys look at Map Map vs Object in JavaScript

Categories

Resources