Find maximum sum path through binary tree - javascript - javascript

I've been trying to figure this problem out for a couple days and can't seem to optimize the solution to make it tenable.
I have a tree that's 100 levels deep, so brute force (2^100 possible combinations?) is obviously not working..
Here is the code I have so far:
// Node constructor | structure of nodes
var Node = function(val) {
this.val = Number(val);
this.left = null;
this.right = null;
}
function maxPathUtil(top, store) {
if (top === null || top === undefined) return 0;
if (top.left === null && top.right === null) {
// console.log("hello");
return top.val;
}
leftSub = maxPathUtil(top.left, store);
rightSub = maxPathUtil(top.right, store);
store[0] = Math.max(store[0], leftSub+rightSub+top.val);
return Math.max(leftSub, rightSub) + top.val;
}
function maxPathSum(top) {
store = [];
store[0] = 0;
maxPathUtil(top, store)
return store[0];
}
var top = nodify(levels);
console.log(maxPathSum(top));
Is there a way to memoize this solution / otherwise improve the big O or is that as efficient as it gets?

So, each node should have ab additional extra property, let's call it "currLength"
When you parse the text file and you add the nodes to the tree, then you need to set the this value to the currLength of the parent node + the value of the current node.
After this you only need to check the bottom nodes of the tree to get the lengths of each path.
If you want to optimize this further, then you can add a currMaxLength variable to the tree, set it to -Infinity initially, and when you add a node with a higher currLength, then you set currMaxLength to currLength.
Keep in mind, this doesn't make it any faster, this just moves the compexity to the init part. It works like insertion sort.

here's how I've solved this problem in JavaScript, hope it helps!
var hasPathSum = function(root, sum) {
if (root == null) {
return false
}
var result = checkTree(root,root.val,sum)
console.log(result)
return result
};
function checkTree(node,currentSum,sum) {
if (currentSum == sum && node.left == null && node.right == null) {
return true
}
var result = false
if (node.left != null) {
result = result || checkTree(node.left,currentSum+node.left.val,sum)
}
if (node.right != null) {
result = result || checkTree(node.right,currentSum+node.right.val,sum)
}
return result
}
also on my Github

function pathSum(root , sum){
//Add Base Case For Recursion
if(root === null)return false;
//Add another base case
if(root.val === sum &&(root.left === null && root.right === null)return true
// here when it reach to the leaf where the next is null for both left and right
return pathSum(root.left , sum - root.val)|| pathSum(root.right ,sum - root.val )
//So In the code above I added (||) because If the first recursion return false, it will execute next recursion and so on
}

Related

What is the size of objects in JavaScript? [duplicate]

I want to know the size occupied by a JavaScript object.
Take the following function:
function Marks(){
this.maxMarks = 100;
}
function Student(){
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
Now I instantiate the student:
var stud = new Student();
so that I can do stuff like
stud.firstName = "new Firstname";
alert(stud.firstName);
stud.marks.maxMarks = 200;
etc.
Now, the stud object will occupy some size in memory. It has some data and more objects.
How do I find out how much memory the stud object occupies? Something like a sizeof() in JavaScript? It would be really awesome if I could find it out in a single function call like sizeof(stud).
I’ve been searching the Internet for months—couldn’t find it (asked in a couple of forums—no replies).
I have re-factored the code in my original answer. I have removed the recursion and removed the assumed existence overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var stack = [ object ];
var bytes = 0;
while ( stack.length ) {
var value = stack.pop();
if ( typeof value === 'boolean' ) {
bytes += 4;
}
else if ( typeof value === 'string' ) {
bytes += value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes += 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList.push( value );
for( var i in value ) {
stack.push( value[ i ] );
}
}
}
return bytes;
}
The Google Chrome Heap Profiler allows you to inspect object memory use.
You need to be able to locate the object in the trace which can be tricky. If you pin the object to the Window global, it is pretty easy to find from the "Containment" listing mode.
In the attached screenshot, I created an object called "testObj" on the window. I then located in the profiler (after making a recording) and it shows the full size of the object and everything in it under "retained size".
More details on the memory breakdowns.
In the above screenshot, the object shows a retained size of 60. I believe the unit is bytes here.
Sometimes I use this to flag really big objects that might be going to the client from the server. It doesn't represent the in memory footprint. It just gets you approximately what it'd cost to send it, or store it.
Also note, it's slow, dev only. But for getting an ballpark answer with one line of code it's been useful for me.
roughObjSize = JSON.stringify(bigObject).length;
I just wrote this to solve a similar (ish) problem. It doesn't exactly do what you may be looking for, ie it doesn't take into account how the interpreter stores the object.
But, if you are using V8, it should give you a fairly ok approximation as the awesome prototyping and hidden classes lick up most of the overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var recurse = function( value )
{
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList[ objectList.length ] = value;
for( i in value ) {
bytes+= 8; // an assumed existence overhead
bytes+= recurse( value[i] )
}
}
return bytes;
}
return recurse( object );
}
Here's a slightly more compact solution to the problem:
const typeSizes = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": item => 2 * item.length,
"object": item => !item ? 0 : Object
.keys(item)
.reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0)
};
const sizeOf = value => typeSizes[typeof value](value);
There is a NPM module to get object sizeof, you can install it with npm install object-sizeof
var sizeof = require('object-sizeof');
// 2B per character, 6 chars total => 12B
console.log(sizeof({abc: 'def'}));
// 8B for Number => 8B
console.log(sizeof(12345));
var param = {
'a': 1,
'b': 2,
'c': {
'd': 4
}
};
// 4 one two-bytes char strings and 3 eighth-bytes numbers => 32B
console.log(sizeof(param));
This is a hacky method, but i tried it twice with different numbers and it seems to be consistent.
What you can do is to try and allocate a huge number of objects, like one or two million objects of the kind you want. Put the objects in an array to prevent the garbage collector from releasing them (note that this will add a slight memory overhead because of the array, but i hope this shouldn't matter and besides if you are going to worry about objects being in memory, you store them somewhere). Add an alert before and after the allocation and in each alert check how much memory the Firefox process is taking. Before you open the page with the test, make sure you have a fresh Firefox instance. Open the page, note the memory usage after the "before" alert is shown. Close the alert, wait for the memory to be allocated. Subtract the new memory from the older and divide it by the amount of allocations. Example:
function Marks()
{
this.maxMarks = 100;
}
function Student()
{
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
var manyObjects = new Array();
alert('before');
for (var i=0; i<2000000; i++)
manyObjects[i] = new Student();
alert('after');
I tried this in my computer and the process had 48352K of memory when the "before" alert was shown. After the allocation, Firefox had 440236K of memory. For 2million allocations, this is about 200 bytes for each object.
I tried it again with 1million allocations and the result was similar: 196 bytes per object (i suppose the extra data in 2mill was used for Array).
So, here is a hacky method that might help you. JavaScript doesn't provide a "sizeof" method for a reason: each JavaScript implementaion is different. In Google Chrome for example the same page uses about 66 bytes for each object (judging from the task manager at least).
Having the same problem. I searched on Google and I want to share with stackoverflow community this solution.
Important:
I used the function shared by Yan Qing on github
https://gist.github.com/zensh/4975495
function memorySizeOf(obj) {
var bytes = 0;
function sizeOf(obj) {
if(obj !== null && obj !== undefined) {
switch(typeof obj) {
case 'number':
bytes += 8;
break;
case 'string':
bytes += obj.length * 2;
break;
case 'boolean':
bytes += 4;
break;
case 'object':
var objClass = Object.prototype.toString.call(obj).slice(8, -1);
if(objClass === 'Object' || objClass === 'Array') {
for(var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
sizeOf(obj[key]);
}
} else bytes += obj.toString().length * 2;
break;
}
}
return bytes;
};
function formatByteSize(bytes) {
if(bytes < 1024) return bytes + " bytes";
else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
else return(bytes / 1073741824).toFixed(3) + " GiB";
};
return formatByteSize(sizeOf(obj));
};
var sizeOfStudentObject = memorySizeOf({Student: {firstName: 'firstName', lastName: 'lastName', marks: 10}});
console.log(sizeOfStudentObject);
What do you think about it?
Sorry I could not comment, so I just continue the work from tomwrong.
This enhanced version will not count object more than once, thus no infinite loop.
Plus, I reckon the key of an object should be also counted, roughly.
function roughSizeOfObject( value, level ) {
if(level == undefined) level = 0;
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if ( typeof value === 'object' ) {
if(value['__visited__']) return 0;
value['__visited__'] = 1;
for( i in value ) {
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= roughSizeOfObject( value[i], 1 )
}
}
if(level == 0){
clear__visited__(value);
}
return bytes;
}
function clear__visited__(value){
if(typeof value == 'object'){
delete value['__visited__'];
for(var i in value){
clear__visited__(value[i]);
}
}
}
roughSizeOfObject(a);
i want to know if my memory reduction efforts actually help in reducing memory
Following up on this comment, here's what you should do:
Try to produce a memory problem - Write code that creates all these objects and graudally increase the upper limit until you ran into a problem (Browser crash, Browser freeze or an Out-Of-memory error). Ideally you should repeat this experiment with different browsers and different operating system.
Now there are two options:
option 1 - You didn't succeed in producing the memory problem. Hence, you are worrying for nothing. You don't have a memory issue and your program is fine.
option 2- you did get a memory problem. Now ask yourself whether the limit at which the problem occurred is reasonable (in other words: is it likely that this amount of objects will be created at normal use of your code). If the answer is 'No' then you're fine. Otherwise you now know how many objects your code can create. Rework the algorithm such that it does not breach this limit.
This Javascript library sizeof.js does the same thing.
Include it like this
<script type="text/javascript" src="sizeof.js"></script>
The sizeof function takes an object as a parameter and returns its approximate size in bytes. For example:
// define an object
var object =
{
'boolean' : true,
'number' : 1,
'string' : 'a',
'array' : [1, 2, 3]
};
// determine the size of the object
var size = sizeof(object);
The sizeof function can handle objects that contain multiple references to other objects and recursive references.
Originally published here.
If your main concern is the memory usage of your Firefox extension, I suggest checking with Mozilla developers.
Mozilla provides on its wiki a list of tools to analyze memory leaks.
Chrome developer tools has this functionality. I found this article very helpful and does exactly what you want:
https://developers.google.com/chrome-developer-tools/docs/heap-profiling
Many thanks to everyone that has been working on code for this!
I just wanted to add that I've been looking for exactly the same thing, but in my case it's for managing a cache of processed objects to avoid having to re-parse and process objects from ajax calls that may or may not have been cached by the browser. This is especially useful for objects that require a lot of processing, usually anything that isn't in JSON format, but it can get very costly to keep these things cached in a large project or an app/extension that is left running for a long time.
Anyway, I use it for something something like:
var myCache = {
cache: {},
order: [],
size: 0,
maxSize: 2 * 1024 * 1024, // 2mb
add: function(key, object) {
// Otherwise add new object
var size = this.getObjectSize(object);
if (size > this.maxSize) return; // Can't store this object
var total = this.size + size;
// Check for existing entry, as replacing it will free up space
if (typeof(this.cache[key]) !== 'undefined') {
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
total -= entry.size;
this.order.splice(i, 1);
break;
}
}
}
while (total > this.maxSize) {
var entry = this.order.shift();
delete this.cache[entry.key];
total -= entry.size;
}
this.cache[key] = object;
this.order.push({ size: size, key: key });
this.size = total;
},
get: function(key) {
var value = this.cache[key];
if (typeof(value) !== 'undefined') { // Return this key for longer
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
this.order.splice(i, 1);
this.order.push(entry);
break;
}
}
}
return value;
},
getObjectSize: function(object) {
// Code from above estimating functions
},
};
It's a simplistic example and may have some errors, but it gives the idea, as you can use it to hold onto static objects (contents won't change) with some degree of intelligence. This can significantly cut down on any expensive processing requirements that the object had to be produced in the first place.
The accepted answer does not work with Map, Set, WeakMap and other iterable objects. (The package object-sizeof, mentioned in other answer, has the same problem).
Here's my fix
export function roughSizeOfObject(object) {
const objectList = [];
const stack = [object];
const bytes = [0];
while (stack.length) {
const value = stack.pop();
if (value == null) bytes[0] += 4;
else if (typeof value === 'boolean') bytes[0] += 4;
else if (typeof value === 'string') bytes[0] += value.length * 2;
else if (typeof value === 'number') bytes[0] += 8;
else if (typeof value === 'object' && objectList.indexOf(value) === -1) {
objectList.push(value);
if (typeof value.byteLength === 'number') bytes[0] += value.byteLength;
else if (value[Symbol.iterator]) {
// eslint-disable-next-line no-restricted-syntax
for (const v of value) stack.push(v);
} else {
Object.keys(value).forEach(k => {
bytes[0] += k.length * 2; stack.push(value[k]);
});
}
}
}
return bytes[0];
}
It also includes some other minor improvements: counts keys storage and works with ArrayBuffer.
function sizeOf(parent_data, size)
{
for (var prop in parent_data)
{
let value = parent_data[prop];
if (typeof value === 'boolean')
{
size += 4;
}
else if (typeof value === 'string')
{
size += value.length * 2;
}
else if (typeof value === 'number')
{
size += 8;
}
else
{
let oldSize = size;
size += sizeOf(value, oldSize) - oldSize;
}
}
return size;
}
function roughSizeOfObject(object)
{
let size = 0;
for each (let prop in object)
{
size += sizeOf(prop, 0);
} // for..
return size;
}
I use Chrome dev tools' Timeline tab, instantiate increasingly large amounts of objects, and get good estimates like that. You can use html like this one below, as boilerplate, and modify it to better simulate the characteristics of your objects (number and types of properties, etc...). You may want to click the trash bit icon at the bottom of that dev tools tab, before and after a run.
<html>
<script>
var size = 1000*100
window.onload = function() {
document.getElementById("quantifier").value = size
}
function scaffold()
{
console.log("processing Scaffold...");
a = new Array
}
function start()
{
size = document.getElementById("quantifier").value
console.log("Starting... quantifier is " + size);
console.log("starting test")
for (i=0; i<size; i++){
a[i]={"some" : "thing"}
}
console.log("done...")
}
function tearDown()
{
console.log("processing teardown");
a.length=0
}
</script>
<body>
<span style="color:green;">Quantifier:</span>
<input id="quantifier" style="color:green;" type="text"></input>
<button onclick="scaffold()">Scaffold</button>
<button onclick="start()">Start</button>
<button onclick="tearDown()">Clean</button>
<br/>
</body>
</html>
Instantiating 2 million objects of just one property each (as in this code above) leads to a rough calculation of 50 bytes per object, on my Chromium, right now. Changing the code to create a random string per object adds some 30 bytes per object, etc.
Hope this helps.
If you need to programatically check for aprox. size of objects you can also check this library http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ that I have been able to use for objects size.
Otherwise I suggest to use the Chrome/Firefox Heap Profiler.
I had problems with the above answer with an ArrayBuffer.
After checking the documentation, I found that ArrayBuffer has a byteLength property which tells me exactly what I need, hence:
function sizeOf(data)
{
if (typeof(data) === 'object')
{
if (data instanceof ArrayBuffer)
{
return data.byteLength;
}
// other objects goes here
}
// non-object cases goes here
}
console.log(sizeOf(new ArrayBuffer(15))); // 15
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength
Building upon the already compact solution from #Dan, here's a self-contained function version of it. Variable names are reduced to single letters for those who just want it to be as compact as possible at the expense of context.
const ns = {};
ns.sizeof = function(v) {
let f = ns.sizeof, //this needs to match the name of the function itself, since arguments.callee.name is defunct
o = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": i => 2 * i.length,
"object": i => !i ? 0 : Object
.keys(i)
.reduce((t, k) => f(k) + f(i[k]) + t, 0)
};
return o[typeof v](v);
};
ns.undef;
ns.bool = true;
ns.num = 1;
ns.string = "Hello";
ns.obj = {
first_name: 'John',
last_name: 'Doe',
born: new Date(1980, 1, 1),
favorite_foods: ['Pizza', 'Salad', 'Indian', 'Sushi'],
can_juggle: true
};
console.log(ns.sizeof(ns.undef));
console.log(ns.sizeof(ns.bool));
console.log(ns.sizeof(ns.num));
console.log(ns.sizeof(ns.string));
console.log(ns.sizeof(ns.obj));
console.log(ns.sizeof(ns.obj.favorite_foods));
I believe you forgot to include 'array'.
typeOf : function(value) {
var s = typeof value;
if (s === 'object')
{
if (value)
{
if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length')) && typeof value.splice === 'function')
{
s = 'array';
}
}
else
{
s = 'null';
}
}
return s;
},
estimateSizeOfObject: function(value, level)
{
if(undefined === level)
level = 0;
var bytes = 0;
if ('boolean' === typeOf(value))
bytes = 4;
else if ('string' === typeOf(value))
bytes = value.length * 2;
else if ('number' === typeOf(value))
bytes = 8;
else if ('object' === typeOf(value) || 'array' === typeOf(value))
{
for(var i in value)
{
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= estimateSizeOfObject(value[i], 1)
}
}
return bytes;
},
formatByteSize : function(bytes)
{
if (bytes < 1024)
return bytes + " bytes";
else
{
var floatNum = bytes/1024;
return floatNum.toFixed(2) + " kb";
}
},
I know this is absolutely not the right way to do it, yet it've helped me a few times in the past to get the approx object file size:
Write your object/response to the console or a new tab, copy the results to a new notepad file, save it, and check the file size. The notepad file itself is just a few bytes, so you'll get a fairly accurate object file size.

How to handle extremely large data in node.js array

I am working on a Node.js server that responds with JSON. I have a legacy server that contains the data. The Node.js server acts as a middle-man connecting the user to the data. The legacy server returns data as a csv with columns being keys and rows being objects. I want to turn this into an array of json objects. I am using this tool to do just that: https://github.com/Keyang/node-csvtojson. I can either have the tool construct the output for me or I can have a function called with each row passed in and construct it myself. I am currently doing the later.
The users of my application can pass in a search value which means only rows that contain this value should be returned. The user can also pass in filter keys and values which means only rows where key contains value for every key and value given should be returned. They can of course give both search and filter values or neither. They also give a sort key which is the key in the objects to sort the array by. They also give me a sort order: ascending or descending. They also give me a page size and offset to return, which is for pagination.
My question is, what is the best way to handle this with data sets that could contain millions of rows? I can't modify the legacy server. Here is what I have. It works but I would like to improve performance as much as possible. Is there a more efficient way to do the sorting, searching, filtering, pagination, etc? Would it be better to add to the array and then sort instead of using a binary search tree and sorting during add? Is there a way I could use streams to improve performance? I expect the server to be limited by CPU performance not RAM. I am looking for any recomendations for better performance. Thanks! :)
EDIT: Also, what part of the below code is blocking?
function searchRow(row, search) {
if (search) {
for (var key in row) {
if (row.hasOwnProperty(key) && row[key].toString().toLowerCase().indexOf(search.toLowerCase()) > -1) {
return true;
}
}
return false;
} else {
return true;
}
}
function filterByField(obj) {
return obj.field === this.valueOf();
}
function filterRow(row, filter) {
if (filter) {
filter = JSON.parse(decodeURIComponent(filter));
var passed = true;
for (var key in filter) {
if (filter.hasOwnProperty(key)) {
var index = row[key].toString().toLowerCase().indexOf(filter[key].toString().toLowerCase());
passed = passed && (index > -1);
}
if (!passed) {
break;
}
}
return passed;
} else {
return true;
}
}
function orderByKey(key, reverse, a, b) {
return function (a, b) {
var x = (a[key] || '').toString().toLowerCase();
var y = (b[key] || '').toString().toLowerCase();
if (x > y) {
return reverse ? -1 : 1;
} else if (y > x) {
return reverse ? 1 : -1;
} else if (hash(a) > hash(b)) {
return reverse ? -1 : 1;
} else if (hash(b) > hash(a)) {
return reverse ? 1 : -1;
} else {
return 0;
}
};
}
function sortedInsert(element, array, key, reverse) {
array.splice(locationOf(element, array, key, reverse) + 1, 0, element);
return array;
}
function locationOf(element, array, key, reverse, start, end) {
if (array.length === 0) {
return -1;
}
start = start || 0;
end = end || array.length;
var pivot = parseInt(start + (end - start) / 2, 10);
var c = orderByKey(key, reverse, element, array[pivot]);
if (end - start <= 1) {
return c == -1 ? pivot - 1 : pivot;
}
switch (c) {
case -1: return locationOf(element, array, key, reverse, start, pivot);
case 0: return pivot;
case 1: return locationOf(element, array, key, reverse, pivot, end);
}
}
function getTable(path, columns, delimiter, query) {
var deferred = q.defer();
var headers = [];
var data = [];
delimiter = delimiter ? delimiter : '\t';
var converter = new Converter({
delimiter: delimiter,
noheader: true,
headers: columns,
workerNum: os.cpus().length,
constructResult: false
});
converter.on("error", function(errMsg, errData) {
deferred.reject(errMsg);
});
converter.on("record_parsed", function(row) {
if (searchRow(row, query.search) && filterRow(row, query.filter)) {
sortedInsert(row, data, query.sort || headers[0].split("!").pop(), query.order === 'desc');
}
});
converter.on("end_parsed", function() {
var offset = parseInt(query.offset || 0);
var limit = parseInt(query.limit || data.length);
var total = data.length;
data = data.slice(offset, offset + limit);
deferred.resolve({
"total": total,
"rows": data
});
});
var options = {
url: config.url + path,
gzip: true,
method: 'GET'
};
request(options, function (error, response, body) {
if (error || response.statusCode != 200) {
deferred.reject(error);
}
}).pipe(converter);
return deferred.promise;
}

Javascript square function

I want to write a function that checks if the given number has a certain order.
The second number has to be the square of the previous number.
The first number can only be 0 - 9.
So for example 2439 would return 'true' because 4 is the square of 2 and 9 is the square of 3.
39416 would also give 'true', and for example 1624 would return 'false'.
I don't really have an idea how to do this. It should be a recursive function but an example of how to do it without recursion would be helpfull too.
I would try something like this:
function isOrdered(input){
var position = 0;
while(position<input.length-2)
{
var currentFirstNumber = parseInt(input[position]);
if(currentFirstNumber<=2) {
if (Math.sqrt(parseInt(input[position + 1])) !== currentFirstNumber)
return false;
else
position+=2;
}
if(currentFirstNumber>=4 && currentFirstNumber<=9)
{
var squared = input.substring(position+1,position+3);
if(Math.sqrt(parseInt(squared))!==currentFirstNumber)
return false;
else
position=position+3;
}
}
return true;
}
console.log(isOrdered("2439")); // outputs true
console.log(isOrdered("39416")); // outputs true
console.log(isOrdered("1624")); // outputs false
I pass the number to the function as a string.
Take a look at this recursive function
function detectOrder(input)
{
var input = input.toString()
var first = input.substr(0,1);
var power = Math.pow(parseInt(first), 2);
var powerLength = power.toString().length;
if ( parseInt(input.substr(1, powerLength)) == power )
{
if (input.length <= 1+powerLength)
{
return true;
}
else
{
return detectOrder(input.substr(1+powerLength));
}
}
else
{
return false;
}
}
As mention in the comment section, OP said that the 'firsts' are limited to 0..9. So the easiest way to accomplish this is by going through the power function instead of the square root function.
UPDATE: Sorry, you asked for JavaScript code. Be careful with the FIRST CALL. if you manually pass to the function the last position, it will return true.
function verification(number, position){
var str = String(number); // Cast number to String
if(str.length > position){ // Verify valid position
var value = str.substr(position, 1); // take the 'first' value
var pow = Math.pow(value, 2); // Calculate the power
// Verify if the next value is equivalent to the power
if(str.indexOf(pow, position) == position + 1){
// Recursive call to verify the next position
return verification(number, position + String(pow).length + 1);
} else {
// If not equivalent, you found an inconsistency.
return false;
}
// If you ran it until you reached the last position, you're good to go.
}else if(str.length == position){
return true;
}
}
console.log(verification(39416, 0)); // True
console.log(verification(39415, 0)); // True
console.log(verification(981524, 0)); // false
console.log(verification(981525, 0)); // true
console.log(verification(98525, 0)); // false

Memory overhead and size of javascript objects [duplicate]

I want to know the size occupied by a JavaScript object.
Take the following function:
function Marks(){
this.maxMarks = 100;
}
function Student(){
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
Now I instantiate the student:
var stud = new Student();
so that I can do stuff like
stud.firstName = "new Firstname";
alert(stud.firstName);
stud.marks.maxMarks = 200;
etc.
Now, the stud object will occupy some size in memory. It has some data and more objects.
How do I find out how much memory the stud object occupies? Something like a sizeof() in JavaScript? It would be really awesome if I could find it out in a single function call like sizeof(stud).
I’ve been searching the Internet for months—couldn’t find it (asked in a couple of forums—no replies).
I have re-factored the code in my original answer. I have removed the recursion and removed the assumed existence overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var stack = [ object ];
var bytes = 0;
while ( stack.length ) {
var value = stack.pop();
if ( typeof value === 'boolean' ) {
bytes += 4;
}
else if ( typeof value === 'string' ) {
bytes += value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes += 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList.push( value );
for( var i in value ) {
stack.push( value[ i ] );
}
}
}
return bytes;
}
The Google Chrome Heap Profiler allows you to inspect object memory use.
You need to be able to locate the object in the trace which can be tricky. If you pin the object to the Window global, it is pretty easy to find from the "Containment" listing mode.
In the attached screenshot, I created an object called "testObj" on the window. I then located in the profiler (after making a recording) and it shows the full size of the object and everything in it under "retained size".
More details on the memory breakdowns.
In the above screenshot, the object shows a retained size of 60. I believe the unit is bytes here.
Sometimes I use this to flag really big objects that might be going to the client from the server. It doesn't represent the in memory footprint. It just gets you approximately what it'd cost to send it, or store it.
Also note, it's slow, dev only. But for getting an ballpark answer with one line of code it's been useful for me.
roughObjSize = JSON.stringify(bigObject).length;
I just wrote this to solve a similar (ish) problem. It doesn't exactly do what you may be looking for, ie it doesn't take into account how the interpreter stores the object.
But, if you are using V8, it should give you a fairly ok approximation as the awesome prototyping and hidden classes lick up most of the overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var recurse = function( value )
{
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList[ objectList.length ] = value;
for( i in value ) {
bytes+= 8; // an assumed existence overhead
bytes+= recurse( value[i] )
}
}
return bytes;
}
return recurse( object );
}
Here's a slightly more compact solution to the problem:
const typeSizes = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": item => 2 * item.length,
"object": item => !item ? 0 : Object
.keys(item)
.reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0)
};
const sizeOf = value => typeSizes[typeof value](value);
There is a NPM module to get object sizeof, you can install it with npm install object-sizeof
var sizeof = require('object-sizeof');
// 2B per character, 6 chars total => 12B
console.log(sizeof({abc: 'def'}));
// 8B for Number => 8B
console.log(sizeof(12345));
var param = {
'a': 1,
'b': 2,
'c': {
'd': 4
}
};
// 4 one two-bytes char strings and 3 eighth-bytes numbers => 32B
console.log(sizeof(param));
This is a hacky method, but i tried it twice with different numbers and it seems to be consistent.
What you can do is to try and allocate a huge number of objects, like one or two million objects of the kind you want. Put the objects in an array to prevent the garbage collector from releasing them (note that this will add a slight memory overhead because of the array, but i hope this shouldn't matter and besides if you are going to worry about objects being in memory, you store them somewhere). Add an alert before and after the allocation and in each alert check how much memory the Firefox process is taking. Before you open the page with the test, make sure you have a fresh Firefox instance. Open the page, note the memory usage after the "before" alert is shown. Close the alert, wait for the memory to be allocated. Subtract the new memory from the older and divide it by the amount of allocations. Example:
function Marks()
{
this.maxMarks = 100;
}
function Student()
{
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
var manyObjects = new Array();
alert('before');
for (var i=0; i<2000000; i++)
manyObjects[i] = new Student();
alert('after');
I tried this in my computer and the process had 48352K of memory when the "before" alert was shown. After the allocation, Firefox had 440236K of memory. For 2million allocations, this is about 200 bytes for each object.
I tried it again with 1million allocations and the result was similar: 196 bytes per object (i suppose the extra data in 2mill was used for Array).
So, here is a hacky method that might help you. JavaScript doesn't provide a "sizeof" method for a reason: each JavaScript implementaion is different. In Google Chrome for example the same page uses about 66 bytes for each object (judging from the task manager at least).
Having the same problem. I searched on Google and I want to share with stackoverflow community this solution.
Important:
I used the function shared by Yan Qing on github
https://gist.github.com/zensh/4975495
function memorySizeOf(obj) {
var bytes = 0;
function sizeOf(obj) {
if(obj !== null && obj !== undefined) {
switch(typeof obj) {
case 'number':
bytes += 8;
break;
case 'string':
bytes += obj.length * 2;
break;
case 'boolean':
bytes += 4;
break;
case 'object':
var objClass = Object.prototype.toString.call(obj).slice(8, -1);
if(objClass === 'Object' || objClass === 'Array') {
for(var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
sizeOf(obj[key]);
}
} else bytes += obj.toString().length * 2;
break;
}
}
return bytes;
};
function formatByteSize(bytes) {
if(bytes < 1024) return bytes + " bytes";
else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
else return(bytes / 1073741824).toFixed(3) + " GiB";
};
return formatByteSize(sizeOf(obj));
};
var sizeOfStudentObject = memorySizeOf({Student: {firstName: 'firstName', lastName: 'lastName', marks: 10}});
console.log(sizeOfStudentObject);
What do you think about it?
Sorry I could not comment, so I just continue the work from tomwrong.
This enhanced version will not count object more than once, thus no infinite loop.
Plus, I reckon the key of an object should be also counted, roughly.
function roughSizeOfObject( value, level ) {
if(level == undefined) level = 0;
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if ( typeof value === 'object' ) {
if(value['__visited__']) return 0;
value['__visited__'] = 1;
for( i in value ) {
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= roughSizeOfObject( value[i], 1 )
}
}
if(level == 0){
clear__visited__(value);
}
return bytes;
}
function clear__visited__(value){
if(typeof value == 'object'){
delete value['__visited__'];
for(var i in value){
clear__visited__(value[i]);
}
}
}
roughSizeOfObject(a);
i want to know if my memory reduction efforts actually help in reducing memory
Following up on this comment, here's what you should do:
Try to produce a memory problem - Write code that creates all these objects and graudally increase the upper limit until you ran into a problem (Browser crash, Browser freeze or an Out-Of-memory error). Ideally you should repeat this experiment with different browsers and different operating system.
Now there are two options:
option 1 - You didn't succeed in producing the memory problem. Hence, you are worrying for nothing. You don't have a memory issue and your program is fine.
option 2- you did get a memory problem. Now ask yourself whether the limit at which the problem occurred is reasonable (in other words: is it likely that this amount of objects will be created at normal use of your code). If the answer is 'No' then you're fine. Otherwise you now know how many objects your code can create. Rework the algorithm such that it does not breach this limit.
This Javascript library sizeof.js does the same thing.
Include it like this
<script type="text/javascript" src="sizeof.js"></script>
The sizeof function takes an object as a parameter and returns its approximate size in bytes. For example:
// define an object
var object =
{
'boolean' : true,
'number' : 1,
'string' : 'a',
'array' : [1, 2, 3]
};
// determine the size of the object
var size = sizeof(object);
The sizeof function can handle objects that contain multiple references to other objects and recursive references.
Originally published here.
If your main concern is the memory usage of your Firefox extension, I suggest checking with Mozilla developers.
Mozilla provides on its wiki a list of tools to analyze memory leaks.
Chrome developer tools has this functionality. I found this article very helpful and does exactly what you want:
https://developers.google.com/chrome-developer-tools/docs/heap-profiling
Many thanks to everyone that has been working on code for this!
I just wanted to add that I've been looking for exactly the same thing, but in my case it's for managing a cache of processed objects to avoid having to re-parse and process objects from ajax calls that may or may not have been cached by the browser. This is especially useful for objects that require a lot of processing, usually anything that isn't in JSON format, but it can get very costly to keep these things cached in a large project or an app/extension that is left running for a long time.
Anyway, I use it for something something like:
var myCache = {
cache: {},
order: [],
size: 0,
maxSize: 2 * 1024 * 1024, // 2mb
add: function(key, object) {
// Otherwise add new object
var size = this.getObjectSize(object);
if (size > this.maxSize) return; // Can't store this object
var total = this.size + size;
// Check for existing entry, as replacing it will free up space
if (typeof(this.cache[key]) !== 'undefined') {
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
total -= entry.size;
this.order.splice(i, 1);
break;
}
}
}
while (total > this.maxSize) {
var entry = this.order.shift();
delete this.cache[entry.key];
total -= entry.size;
}
this.cache[key] = object;
this.order.push({ size: size, key: key });
this.size = total;
},
get: function(key) {
var value = this.cache[key];
if (typeof(value) !== 'undefined') { // Return this key for longer
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
this.order.splice(i, 1);
this.order.push(entry);
break;
}
}
}
return value;
},
getObjectSize: function(object) {
// Code from above estimating functions
},
};
It's a simplistic example and may have some errors, but it gives the idea, as you can use it to hold onto static objects (contents won't change) with some degree of intelligence. This can significantly cut down on any expensive processing requirements that the object had to be produced in the first place.
The accepted answer does not work with Map, Set, WeakMap and other iterable objects. (The package object-sizeof, mentioned in other answer, has the same problem).
Here's my fix
export function roughSizeOfObject(object) {
const objectList = [];
const stack = [object];
const bytes = [0];
while (stack.length) {
const value = stack.pop();
if (value == null) bytes[0] += 4;
else if (typeof value === 'boolean') bytes[0] += 4;
else if (typeof value === 'string') bytes[0] += value.length * 2;
else if (typeof value === 'number') bytes[0] += 8;
else if (typeof value === 'object' && objectList.indexOf(value) === -1) {
objectList.push(value);
if (typeof value.byteLength === 'number') bytes[0] += value.byteLength;
else if (value[Symbol.iterator]) {
// eslint-disable-next-line no-restricted-syntax
for (const v of value) stack.push(v);
} else {
Object.keys(value).forEach(k => {
bytes[0] += k.length * 2; stack.push(value[k]);
});
}
}
}
return bytes[0];
}
It also includes some other minor improvements: counts keys storage and works with ArrayBuffer.
function sizeOf(parent_data, size)
{
for (var prop in parent_data)
{
let value = parent_data[prop];
if (typeof value === 'boolean')
{
size += 4;
}
else if (typeof value === 'string')
{
size += value.length * 2;
}
else if (typeof value === 'number')
{
size += 8;
}
else
{
let oldSize = size;
size += sizeOf(value, oldSize) - oldSize;
}
}
return size;
}
function roughSizeOfObject(object)
{
let size = 0;
for each (let prop in object)
{
size += sizeOf(prop, 0);
} // for..
return size;
}
I use Chrome dev tools' Timeline tab, instantiate increasingly large amounts of objects, and get good estimates like that. You can use html like this one below, as boilerplate, and modify it to better simulate the characteristics of your objects (number and types of properties, etc...). You may want to click the trash bit icon at the bottom of that dev tools tab, before and after a run.
<html>
<script>
var size = 1000*100
window.onload = function() {
document.getElementById("quantifier").value = size
}
function scaffold()
{
console.log("processing Scaffold...");
a = new Array
}
function start()
{
size = document.getElementById("quantifier").value
console.log("Starting... quantifier is " + size);
console.log("starting test")
for (i=0; i<size; i++){
a[i]={"some" : "thing"}
}
console.log("done...")
}
function tearDown()
{
console.log("processing teardown");
a.length=0
}
</script>
<body>
<span style="color:green;">Quantifier:</span>
<input id="quantifier" style="color:green;" type="text"></input>
<button onclick="scaffold()">Scaffold</button>
<button onclick="start()">Start</button>
<button onclick="tearDown()">Clean</button>
<br/>
</body>
</html>
Instantiating 2 million objects of just one property each (as in this code above) leads to a rough calculation of 50 bytes per object, on my Chromium, right now. Changing the code to create a random string per object adds some 30 bytes per object, etc.
Hope this helps.
If you need to programatically check for aprox. size of objects you can also check this library http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ that I have been able to use for objects size.
Otherwise I suggest to use the Chrome/Firefox Heap Profiler.
I had problems with the above answer with an ArrayBuffer.
After checking the documentation, I found that ArrayBuffer has a byteLength property which tells me exactly what I need, hence:
function sizeOf(data)
{
if (typeof(data) === 'object')
{
if (data instanceof ArrayBuffer)
{
return data.byteLength;
}
// other objects goes here
}
// non-object cases goes here
}
console.log(sizeOf(new ArrayBuffer(15))); // 15
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength
Building upon the already compact solution from #Dan, here's a self-contained function version of it. Variable names are reduced to single letters for those who just want it to be as compact as possible at the expense of context.
const ns = {};
ns.sizeof = function(v) {
let f = ns.sizeof, //this needs to match the name of the function itself, since arguments.callee.name is defunct
o = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": i => 2 * i.length,
"object": i => !i ? 0 : Object
.keys(i)
.reduce((t, k) => f(k) + f(i[k]) + t, 0)
};
return o[typeof v](v);
};
ns.undef;
ns.bool = true;
ns.num = 1;
ns.string = "Hello";
ns.obj = {
first_name: 'John',
last_name: 'Doe',
born: new Date(1980, 1, 1),
favorite_foods: ['Pizza', 'Salad', 'Indian', 'Sushi'],
can_juggle: true
};
console.log(ns.sizeof(ns.undef));
console.log(ns.sizeof(ns.bool));
console.log(ns.sizeof(ns.num));
console.log(ns.sizeof(ns.string));
console.log(ns.sizeof(ns.obj));
console.log(ns.sizeof(ns.obj.favorite_foods));
I believe you forgot to include 'array'.
typeOf : function(value) {
var s = typeof value;
if (s === 'object')
{
if (value)
{
if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length')) && typeof value.splice === 'function')
{
s = 'array';
}
}
else
{
s = 'null';
}
}
return s;
},
estimateSizeOfObject: function(value, level)
{
if(undefined === level)
level = 0;
var bytes = 0;
if ('boolean' === typeOf(value))
bytes = 4;
else if ('string' === typeOf(value))
bytes = value.length * 2;
else if ('number' === typeOf(value))
bytes = 8;
else if ('object' === typeOf(value) || 'array' === typeOf(value))
{
for(var i in value)
{
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= estimateSizeOfObject(value[i], 1)
}
}
return bytes;
},
formatByteSize : function(bytes)
{
if (bytes < 1024)
return bytes + " bytes";
else
{
var floatNum = bytes/1024;
return floatNum.toFixed(2) + " kb";
}
},
I know this is absolutely not the right way to do it, yet it've helped me a few times in the past to get the approx object file size:
Write your object/response to the console or a new tab, copy the results to a new notepad file, save it, and check the file size. The notepad file itself is just a few bytes, so you'll get a fairly accurate object file size.

How to get the size of a JavaScript object?

I want to know the size occupied by a JavaScript object.
Take the following function:
function Marks(){
this.maxMarks = 100;
}
function Student(){
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
Now I instantiate the student:
var stud = new Student();
so that I can do stuff like
stud.firstName = "new Firstname";
alert(stud.firstName);
stud.marks.maxMarks = 200;
etc.
Now, the stud object will occupy some size in memory. It has some data and more objects.
How do I find out how much memory the stud object occupies? Something like a sizeof() in JavaScript? It would be really awesome if I could find it out in a single function call like sizeof(stud).
I’ve been searching the Internet for months—couldn’t find it (asked in a couple of forums—no replies).
I have re-factored the code in my original answer. I have removed the recursion and removed the assumed existence overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var stack = [ object ];
var bytes = 0;
while ( stack.length ) {
var value = stack.pop();
if ( typeof value === 'boolean' ) {
bytes += 4;
}
else if ( typeof value === 'string' ) {
bytes += value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes += 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList.push( value );
for( var i in value ) {
stack.push( value[ i ] );
}
}
}
return bytes;
}
The Google Chrome Heap Profiler allows you to inspect object memory use.
You need to be able to locate the object in the trace which can be tricky. If you pin the object to the Window global, it is pretty easy to find from the "Containment" listing mode.
In the attached screenshot, I created an object called "testObj" on the window. I then located in the profiler (after making a recording) and it shows the full size of the object and everything in it under "retained size".
More details on the memory breakdowns.
In the above screenshot, the object shows a retained size of 60. I believe the unit is bytes here.
Sometimes I use this to flag really big objects that might be going to the client from the server. It doesn't represent the in memory footprint. It just gets you approximately what it'd cost to send it, or store it.
Also note, it's slow, dev only. But for getting an ballpark answer with one line of code it's been useful for me.
roughObjSize = JSON.stringify(bigObject).length;
I just wrote this to solve a similar (ish) problem. It doesn't exactly do what you may be looking for, ie it doesn't take into account how the interpreter stores the object.
But, if you are using V8, it should give you a fairly ok approximation as the awesome prototyping and hidden classes lick up most of the overhead.
function roughSizeOfObject( object ) {
var objectList = [];
var recurse = function( value )
{
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList[ objectList.length ] = value;
for( i in value ) {
bytes+= 8; // an assumed existence overhead
bytes+= recurse( value[i] )
}
}
return bytes;
}
return recurse( object );
}
Here's a slightly more compact solution to the problem:
const typeSizes = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": item => 2 * item.length,
"object": item => !item ? 0 : Object
.keys(item)
.reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0)
};
const sizeOf = value => typeSizes[typeof value](value);
There is a NPM module to get object sizeof, you can install it with npm install object-sizeof
var sizeof = require('object-sizeof');
// 2B per character, 6 chars total => 12B
console.log(sizeof({abc: 'def'}));
// 8B for Number => 8B
console.log(sizeof(12345));
var param = {
'a': 1,
'b': 2,
'c': {
'd': 4
}
};
// 4 one two-bytes char strings and 3 eighth-bytes numbers => 32B
console.log(sizeof(param));
This is a hacky method, but i tried it twice with different numbers and it seems to be consistent.
What you can do is to try and allocate a huge number of objects, like one or two million objects of the kind you want. Put the objects in an array to prevent the garbage collector from releasing them (note that this will add a slight memory overhead because of the array, but i hope this shouldn't matter and besides if you are going to worry about objects being in memory, you store them somewhere). Add an alert before and after the allocation and in each alert check how much memory the Firefox process is taking. Before you open the page with the test, make sure you have a fresh Firefox instance. Open the page, note the memory usage after the "before" alert is shown. Close the alert, wait for the memory to be allocated. Subtract the new memory from the older and divide it by the amount of allocations. Example:
function Marks()
{
this.maxMarks = 100;
}
function Student()
{
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
var manyObjects = new Array();
alert('before');
for (var i=0; i<2000000; i++)
manyObjects[i] = new Student();
alert('after');
I tried this in my computer and the process had 48352K of memory when the "before" alert was shown. After the allocation, Firefox had 440236K of memory. For 2million allocations, this is about 200 bytes for each object.
I tried it again with 1million allocations and the result was similar: 196 bytes per object (i suppose the extra data in 2mill was used for Array).
So, here is a hacky method that might help you. JavaScript doesn't provide a "sizeof" method for a reason: each JavaScript implementaion is different. In Google Chrome for example the same page uses about 66 bytes for each object (judging from the task manager at least).
Having the same problem. I searched on Google and I want to share with stackoverflow community this solution.
Important:
I used the function shared by Yan Qing on github
https://gist.github.com/zensh/4975495
function memorySizeOf(obj) {
var bytes = 0;
function sizeOf(obj) {
if(obj !== null && obj !== undefined) {
switch(typeof obj) {
case 'number':
bytes += 8;
break;
case 'string':
bytes += obj.length * 2;
break;
case 'boolean':
bytes += 4;
break;
case 'object':
var objClass = Object.prototype.toString.call(obj).slice(8, -1);
if(objClass === 'Object' || objClass === 'Array') {
for(var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
sizeOf(obj[key]);
}
} else bytes += obj.toString().length * 2;
break;
}
}
return bytes;
};
function formatByteSize(bytes) {
if(bytes < 1024) return bytes + " bytes";
else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
else return(bytes / 1073741824).toFixed(3) + " GiB";
};
return formatByteSize(sizeOf(obj));
};
var sizeOfStudentObject = memorySizeOf({Student: {firstName: 'firstName', lastName: 'lastName', marks: 10}});
console.log(sizeOfStudentObject);
What do you think about it?
Sorry I could not comment, so I just continue the work from tomwrong.
This enhanced version will not count object more than once, thus no infinite loop.
Plus, I reckon the key of an object should be also counted, roughly.
function roughSizeOfObject( value, level ) {
if(level == undefined) level = 0;
var bytes = 0;
if ( typeof value === 'boolean' ) {
bytes = 4;
}
else if ( typeof value === 'string' ) {
bytes = value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes = 8;
}
else if ( typeof value === 'object' ) {
if(value['__visited__']) return 0;
value['__visited__'] = 1;
for( i in value ) {
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= roughSizeOfObject( value[i], 1 )
}
}
if(level == 0){
clear__visited__(value);
}
return bytes;
}
function clear__visited__(value){
if(typeof value == 'object'){
delete value['__visited__'];
for(var i in value){
clear__visited__(value[i]);
}
}
}
roughSizeOfObject(a);
i want to know if my memory reduction efforts actually help in reducing memory
Following up on this comment, here's what you should do:
Try to produce a memory problem - Write code that creates all these objects and graudally increase the upper limit until you ran into a problem (Browser crash, Browser freeze or an Out-Of-memory error). Ideally you should repeat this experiment with different browsers and different operating system.
Now there are two options:
option 1 - You didn't succeed in producing the memory problem. Hence, you are worrying for nothing. You don't have a memory issue and your program is fine.
option 2- you did get a memory problem. Now ask yourself whether the limit at which the problem occurred is reasonable (in other words: is it likely that this amount of objects will be created at normal use of your code). If the answer is 'No' then you're fine. Otherwise you now know how many objects your code can create. Rework the algorithm such that it does not breach this limit.
This Javascript library sizeof.js does the same thing.
Include it like this
<script type="text/javascript" src="sizeof.js"></script>
The sizeof function takes an object as a parameter and returns its approximate size in bytes. For example:
// define an object
var object =
{
'boolean' : true,
'number' : 1,
'string' : 'a',
'array' : [1, 2, 3]
};
// determine the size of the object
var size = sizeof(object);
The sizeof function can handle objects that contain multiple references to other objects and recursive references.
Originally published here.
If your main concern is the memory usage of your Firefox extension, I suggest checking with Mozilla developers.
Mozilla provides on its wiki a list of tools to analyze memory leaks.
Chrome developer tools has this functionality. I found this article very helpful and does exactly what you want:
https://developers.google.com/chrome-developer-tools/docs/heap-profiling
Many thanks to everyone that has been working on code for this!
I just wanted to add that I've been looking for exactly the same thing, but in my case it's for managing a cache of processed objects to avoid having to re-parse and process objects from ajax calls that may or may not have been cached by the browser. This is especially useful for objects that require a lot of processing, usually anything that isn't in JSON format, but it can get very costly to keep these things cached in a large project or an app/extension that is left running for a long time.
Anyway, I use it for something something like:
var myCache = {
cache: {},
order: [],
size: 0,
maxSize: 2 * 1024 * 1024, // 2mb
add: function(key, object) {
// Otherwise add new object
var size = this.getObjectSize(object);
if (size > this.maxSize) return; // Can't store this object
var total = this.size + size;
// Check for existing entry, as replacing it will free up space
if (typeof(this.cache[key]) !== 'undefined') {
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
total -= entry.size;
this.order.splice(i, 1);
break;
}
}
}
while (total > this.maxSize) {
var entry = this.order.shift();
delete this.cache[entry.key];
total -= entry.size;
}
this.cache[key] = object;
this.order.push({ size: size, key: key });
this.size = total;
},
get: function(key) {
var value = this.cache[key];
if (typeof(value) !== 'undefined') { // Return this key for longer
for (var i = 0; i < this.order.length; ++i) {
var entry = this.order[i];
if (entry.key === key) {
this.order.splice(i, 1);
this.order.push(entry);
break;
}
}
}
return value;
},
getObjectSize: function(object) {
// Code from above estimating functions
},
};
It's a simplistic example and may have some errors, but it gives the idea, as you can use it to hold onto static objects (contents won't change) with some degree of intelligence. This can significantly cut down on any expensive processing requirements that the object had to be produced in the first place.
The accepted answer does not work with Map, Set, WeakMap and other iterable objects. (The package object-sizeof, mentioned in other answer, has the same problem).
Here's my fix
export function roughSizeOfObject(object) {
const objectList = [];
const stack = [object];
const bytes = [0];
while (stack.length) {
const value = stack.pop();
if (value == null) bytes[0] += 4;
else if (typeof value === 'boolean') bytes[0] += 4;
else if (typeof value === 'string') bytes[0] += value.length * 2;
else if (typeof value === 'number') bytes[0] += 8;
else if (typeof value === 'object' && objectList.indexOf(value) === -1) {
objectList.push(value);
if (typeof value.byteLength === 'number') bytes[0] += value.byteLength;
else if (value[Symbol.iterator]) {
// eslint-disable-next-line no-restricted-syntax
for (const v of value) stack.push(v);
} else {
Object.keys(value).forEach(k => {
bytes[0] += k.length * 2; stack.push(value[k]);
});
}
}
}
return bytes[0];
}
It also includes some other minor improvements: counts keys storage and works with ArrayBuffer.
function sizeOf(parent_data, size)
{
for (var prop in parent_data)
{
let value = parent_data[prop];
if (typeof value === 'boolean')
{
size += 4;
}
else if (typeof value === 'string')
{
size += value.length * 2;
}
else if (typeof value === 'number')
{
size += 8;
}
else
{
let oldSize = size;
size += sizeOf(value, oldSize) - oldSize;
}
}
return size;
}
function roughSizeOfObject(object)
{
let size = 0;
for each (let prop in object)
{
size += sizeOf(prop, 0);
} // for..
return size;
}
I use Chrome dev tools' Timeline tab, instantiate increasingly large amounts of objects, and get good estimates like that. You can use html like this one below, as boilerplate, and modify it to better simulate the characteristics of your objects (number and types of properties, etc...). You may want to click the trash bit icon at the bottom of that dev tools tab, before and after a run.
<html>
<script>
var size = 1000*100
window.onload = function() {
document.getElementById("quantifier").value = size
}
function scaffold()
{
console.log("processing Scaffold...");
a = new Array
}
function start()
{
size = document.getElementById("quantifier").value
console.log("Starting... quantifier is " + size);
console.log("starting test")
for (i=0; i<size; i++){
a[i]={"some" : "thing"}
}
console.log("done...")
}
function tearDown()
{
console.log("processing teardown");
a.length=0
}
</script>
<body>
<span style="color:green;">Quantifier:</span>
<input id="quantifier" style="color:green;" type="text"></input>
<button onclick="scaffold()">Scaffold</button>
<button onclick="start()">Start</button>
<button onclick="tearDown()">Clean</button>
<br/>
</body>
</html>
Instantiating 2 million objects of just one property each (as in this code above) leads to a rough calculation of 50 bytes per object, on my Chromium, right now. Changing the code to create a random string per object adds some 30 bytes per object, etc.
Hope this helps.
If you need to programatically check for aprox. size of objects you can also check this library http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/ that I have been able to use for objects size.
Otherwise I suggest to use the Chrome/Firefox Heap Profiler.
I had problems with the above answer with an ArrayBuffer.
After checking the documentation, I found that ArrayBuffer has a byteLength property which tells me exactly what I need, hence:
function sizeOf(data)
{
if (typeof(data) === 'object')
{
if (data instanceof ArrayBuffer)
{
return data.byteLength;
}
// other objects goes here
}
// non-object cases goes here
}
console.log(sizeOf(new ArrayBuffer(15))); // 15
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength
Building upon the already compact solution from #Dan, here's a self-contained function version of it. Variable names are reduced to single letters for those who just want it to be as compact as possible at the expense of context.
const ns = {};
ns.sizeof = function(v) {
let f = ns.sizeof, //this needs to match the name of the function itself, since arguments.callee.name is defunct
o = {
"undefined": () => 0,
"boolean": () => 4,
"number": () => 8,
"string": i => 2 * i.length,
"object": i => !i ? 0 : Object
.keys(i)
.reduce((t, k) => f(k) + f(i[k]) + t, 0)
};
return o[typeof v](v);
};
ns.undef;
ns.bool = true;
ns.num = 1;
ns.string = "Hello";
ns.obj = {
first_name: 'John',
last_name: 'Doe',
born: new Date(1980, 1, 1),
favorite_foods: ['Pizza', 'Salad', 'Indian', 'Sushi'],
can_juggle: true
};
console.log(ns.sizeof(ns.undef));
console.log(ns.sizeof(ns.bool));
console.log(ns.sizeof(ns.num));
console.log(ns.sizeof(ns.string));
console.log(ns.sizeof(ns.obj));
console.log(ns.sizeof(ns.obj.favorite_foods));
I believe you forgot to include 'array'.
typeOf : function(value) {
var s = typeof value;
if (s === 'object')
{
if (value)
{
if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length')) && typeof value.splice === 'function')
{
s = 'array';
}
}
else
{
s = 'null';
}
}
return s;
},
estimateSizeOfObject: function(value, level)
{
if(undefined === level)
level = 0;
var bytes = 0;
if ('boolean' === typeOf(value))
bytes = 4;
else if ('string' === typeOf(value))
bytes = value.length * 2;
else if ('number' === typeOf(value))
bytes = 8;
else if ('object' === typeOf(value) || 'array' === typeOf(value))
{
for(var i in value)
{
bytes += i.length * 2;
bytes+= 8; // an assumed existence overhead
bytes+= estimateSizeOfObject(value[i], 1)
}
}
return bytes;
},
formatByteSize : function(bytes)
{
if (bytes < 1024)
return bytes + " bytes";
else
{
var floatNum = bytes/1024;
return floatNum.toFixed(2) + " kb";
}
},
I know this is absolutely not the right way to do it, yet it've helped me a few times in the past to get the approx object file size:
Write your object/response to the console or a new tab, copy the results to a new notepad file, save it, and check the file size. The notepad file itself is just a few bytes, so you'll get a fairly accurate object file size.

Categories

Resources