473,386 Members | 1,830 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

object augmentation and memory usage

I have a script which uses a lot of object augmentation (in order to
extend the functionality of DOM elements), and I'm clearly stressing
out my browser (I rapidly get to a point where Firefox is telling me
that the script is "unresponsive", often more than once. I'm not sure
if it's simply execution time or memory usage.

My question is this: if I augment an object thusly:

function TestAug() {
this.fun = function() {
//do something
}
}

function Test() {
var test = new Object();
TestAug.call(test);
return test;
}

Then I create, oh, 800 Test objects, what is my memory usage? Are
augmented members, such as fun, only stored in a single place, and
merely accessed as instance methods through the magic of call, or is
call basically adding a whole new copy of the function, with attendant
time/memory usage, to the object passed to it? The books and resources
I've found all discuss memory issues around class methods, instance
methods, prototyping, etc., but are vague in discussing how call works.

Jan 26 '06 #1
8 1723
Gawain Lavers wrote:
I have a script which uses a lot of object augmentation (in order to
extend the functionality of DOM elements), and I'm clearly stressing
out my browser (I rapidly get to a point where Firefox is telling me
that the script is "unresponsive", often more than once. I'm not sure
if it's simply execution time or memory usage.
The warning message is due to run-time always. However, the latter may be
affected by increased memory usage, forcing the operating system to enlarge
the swap file or to do more swapping than usual.
My question is this: if I augment an object thusly:

function TestAug() {
this.fun = function() {
//do something
}
}

function Test() {
var test = new Object();
TestAug.call(test);
return test;
}

Then I create, oh, 800 Test objects, what is my memory usage?
A considerably large one.
Are augmented members, such as fun, only stored in a single place, and
merely accessed as instance methods through the magic of call, or is
call basically adding a whole new copy of the function, with attendant
time/memory usage, to the object passed to it?


With this approach, the creation of each new object `o' creates a new
Function object (that `o.fun' refers to) via the `function' expression
in turn. Use prototype objects to avoid that:

function TestAug()
{
}

TestAug.prototype.fun = function()
{
// do something
}

var test = new TestAug();
PointedEars
Jan 26 '06 #2
Thomas 'PointedEars' Lahn wrote on 26 jan 2006 in comp.lang.javascript:
The warning message is due to run-time always.


Eh?

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Jan 26 '06 #3
Yeah, prototype is clearly ideal, but I unfortunately don't have that
option -- perhaps a more clear example:

function DivAug() {
this.fun = function() {
//do stuff
}
}

function MyDiv() {
var div = document.createElement('div');
DivAug.call(div);
return div;
}

The idea I had was that rather than create an external infrastructure
which would manage my DOM structure, I would simply augment the DOM
elements so that they would know what to do with themselves.
Unfortunately, I can't muck with a DOM element's prototype. If call
creates a new copy of the functions methods with invocation, I guess
I'm going to have to rethink everything from scratch. Thanks for the
(albeit disappointing) info.

By the way, does this not render object augmentation essentially
useless in all but trivial cases?

Jan 26 '06 #4
VK

Gawain Lavers wrote:
My question is this: if I augment an object thusly:

function TestAug() {
this.fun = function() {
//do something
}
}

function Test() {
var test = new Object();
TestAug.call(test);
return test;
}
Any particular reason to make the approach so... interesting? ;-)
function foobar() {
// do something
}

function SuperAug() {
this.bar = 'bar';
}

function TestAug() {
SuperAug.call(this);
this.foo = function() {
//do something
}
this.foobar = foobar;
}

function test() {
glbStack = new Array();
for (var i=0; i<10000; i++) {
glbStack.push(new TestAug());
}
alert('Created '+glbStack.length+' instances of TestAug');
}

Then I create, oh, 800 Test objects, what is my memory usage? Are
augmented members, such as fun, only stored in a single place, and
merely accessed as instance methods through the magic of call, or is
call basically adding a whole new copy of the function, with attendant
time/memory usage, to the object passed to it?
In the sample above each of 10,000 TestAug instances has its own copy
of foo() method, its own copy of bar property (inherited from SuperAug)
and there is one copy of foobar method for all 10,000 instances.
The books and resources
I've found all discuss memory issues around class methods, instance
methods, prototyping, etc., but are vague in discussing how call works.


It is understandable because call(), apply(), .constructor, instanceof
are members of other dark side of JavaScript which is not suitable to
discuss in a rifined society. :-)

An understandable description may require some terrible words to
pronounce. Without these words an understandable description is as
difficult as qrfpevor gur vagrepbhefr cebprff jvgubhg hfvat gur jbeq
CRAVF.

:-)

But fully prototype-based inheritance is also well accepted and
functional option.

Jan 26 '06 #5
VK

Gawain Lavers wrote:
Yeah, prototype is clearly ideal, but I unfortunately don't have that
option -- perhaps a more clear example:

function DivAug() {
this.fun = function() {
//do stuff
}
}

function MyDiv() {
var div = document.createElement('div');
DivAug.call(div);
return div;
}

The idea I had was that rather than create an external infrastructure
which would manage my DOM structure, I would simply augment the DOM
elements so that they would know what to do with themselves.
Unfortunately, I can't muck with a DOM element's prototype. If call
creates a new copy of the functions methods with invocation, I guess
I'm going to have to rethink everything from scratch.


You will have to rethink your approach but not because of call() -
call() merely replaces constructor context, so is it going to be a
static method or not depends on constructor, not on call() usage.

The catch is that at least IE doesn't allow you to treat DOM elements
like JavaScript Objects (like one you're getting from new Object() ).
What you can is:

1) add allowed event listeners to a DOM element.
2) attach external behaviors to DOM element (IE only)
3) create JavaScript objects having DOM elements as their members

The last approach may work universally for you. Say:

function AmazingDIV() {
this.$ = document.createElement('DIV');
// ...
this.addTo = function(trg) {trg.appendChild(this.$);}
}

var myDIV = new AmazingDIV();
myDIV.addTo(document.body);

And you are welcome to make addTo method static.

Jan 27 '06 #6
Gawain Lavers wrote:
Yeah, prototype is clearly ideal, but I unfortunately don't
have that option -- perhaps a more clear example:

function DivAug() {
this.fun = function() {
//do stuff
}
}
The comment "do stuff" may not provide enough clarity as inner functions
(declarations or expressions) have a specific role in javascript in that
their use may forms closures:-

<URL: http://www.jibbering.com/faq/faq_notes/closures.html >

In this case it is difficult to see any advantage in using an inner
function expression as the outer function does not have any parameters,
local variables or inner function declarations, so the inner function's
'environment' is empty. Because inner functions may form closures it is
necessary for each such function object to be unique. The language's
specification allows function objects to be re-used when it is
impossible to externally observe the difference between a re-used
function object and two instances of a function object. The observable
difference would relate to the function's internal [[Scope]] property,
and your inner functions would have indistinguishable [[Scope]]
properties because their outer function has no parameters, local
variables or inner function declarations. So it would be possible for an
ECMAScript implementation to execute your code and not be creating a new
function object with each execution of the - DivAug - method. However,
experimentation has revealed no evidence of any ECMAScript
implementations that take advantage of this permitted optimisation.

Generally, you would not want to use an inner function at all unless you
were taking advantage of its special status as an inner function, and
the closure formed by its creation/use.
function MyDiv() {
var div = document.createElement('div');
DivAug.call(div);
return div;
}

The idea I had was that rather than create an external
infrastructure which would manage my DOM structure,
I would simply augment the DOM elements so that they would
know what to do with themselves.
Without any specific example it is not practical to say anything about
this idea.
Unfortunately, I can't muck with a DOM element's prototype.
You certainly cannot on most browsers, which is practically the same as
not being able to at all.
If call creates a new copy of the functions methods with
invocation,
Don't blame this on the function's call method, it is true of inner
functions on all outer function calls. And it is a valuable and
exploitable feature of the language.

And you don't need to use the call method here (indeed you almost never
need to use the call method).
I guess I'm going to have to rethink everything from scratch.
Not at all. You just need to augment all the DIV elements created with
references to a single function object. You could define that function
globally:-

function forDivFun(){
//do stuff
}

- and either directly augment the DIVs following creation:-

var div = document.createElement('div');
div.fun = forDivFun;

- or have another function do the augmentation:-

function DivAug(div){
div.fun = forDivFun;
}

You probably will not want to (should not want to) define the functions
that will act as methods of your objects globally, but you have many
methods of creating such method in a 'private' scope. For example, the
inline execution of a function expression:-

var divAug = (function(){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
return (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
});
})();

The inline execution of the function expression only happens once (as
the script loads) so the inner functions - forDivFun - and - forDivBar -
are only created once, but the function returned and assigned to the
global - divAug - variable is able to assign references to those
function object instances to all the DIVs passed to it as arguments (-
divAug(div) -).

The main drawback with the inline execution of a function expression is
that you cannot use the - divAug - function until after the source code
for it has been executed, so the order of the code becomes important
(rarely a significant problem).

An alternative 'private' scope strategy is the "Russian doll" pattern
(named as such because the outer aspect of a function is replaced with
smaller, more specific, inner aspect during its execution):-

fucntion divAug(div){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
(divAug = (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
}))(div);
div = null;
}

When this function is called for the first time (as - divAug(div); - the
two inner functions - forDivFun - and - forDivBar - are created and then
the global - divAug - function is replaced with an inner function that
has access to - forDivFun - and - forDivBar -. This new function is
called, passing on the div parameter of the outer function so it may be
augmented. Finally the - div - parameter is assigned null so that no DOM
element references are preserved in the closure.

Following the first call to the above function all subsequent calls
transparently execute only the inner function that replaced it. (Thus
the to - forDivFun - and - forDivBar - function objects are only created
once but may be assigned to all DIVs to be augmented).

This strategy means that the set-up/configuration of the divAug function
is delayed until its first use.
Thanks for the (albeit disappointing) info.

By the way, does this not render object augmentation
essentially useless in all but trivial cases?


Augmentation is completely viable, though augmenting 800+ DOM elements
seems a bit extreme. But ore information/context would be needed to
fairly judge the idea.

Richard.
Jan 27 '06 #7
Gawain Lavers wrote:
Yeah,
"Yeah"?

<URL:http://jibbering.com/faq/faq_notes/pots1.html#ps1Post>
<URL:http://www.safalra.com/special/googlegroupsreply/>
prototype is clearly ideal, but I unfortunately don't have that
option -- perhaps a more clear example:

function DivAug() {
this.fun = function() {
//do stuff
}
}

function MyDiv() {
var div = document.createElement('div');
DivAug.call(div);
return div;
}

The idea I had was that rather than create an external infrastructure
which would manage my DOM structure, I would simply augment the DOM
elements so that they would know what to do with themselves.
Unfortunately, I can't muck with a DOM element's prototype.
You can in Gecko-based UAs. And in all other UAs, the above is error-prone
as you are trying to augment a _host object_ [referred to by `div' in
MyDiv() and `this' in DivAug()]. In ECMAScript implementations, a host
object may implement the internal [[Put]] method required to add a property
to an object or change the property value different than specified or not
at all.
[...]
By the way, does this not render object augmentation essentially
useless in all but trivial cases?


No, it does not, for appropriate values of "trivial".
PointedEars
Jan 27 '06 #8
Richard Cornford wrote:
You probably will not want to (should not want to) define the functions
that will act as methods of your objects globally, but you have many
methods of creating such method in a 'private' scope. For example, the
inline execution of a function expression:-
And that nails my problem exactly -- I knew full well how to attach a
function in that manner, but had just screened it out mentally because
I didn't want to "pollute" the global namespace. In retrospect, it was
foolish for me to not figure out how call() would behave if I defined
inner functions in that manner.
var divAug = (function(){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
return (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
});
})();
<snip>
fucntion divAug(div){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
(divAug = (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
}))(div);
div = null;
}
That took me a while to figure out, but that's pretty much exactly what
I need. Cryptic, but fun. For the moment I've just wrapped the
methods for my augmenting "classes" in simple objects, but I'll
probably start trying this out soon. I'm still getting one or two
warnings on occasion in Firefox, but that's on an underpowered laptop.
Augmentation is completely viable, though augmenting 800+ DOM elements
seems a bit extreme. But ore information/context would be needed to
fairly judge the idea.

Richard.


It's a part of an internal web application where users score observed
genetic expression from experimental results. The 800+ actually refers
to a listing of anatomy features (from system to organ to organ
sub-region to cell type) -- each of these having a number of data
points that the users need to be able to set -- about 20 or so "active"
html elements being used to provide pulldown menus, links, and form
fields for each anatomy feature. The scoring widgets themselves are
somewhat complex, and choices in one part of the tree can influence
scores in other parts. Fortunately, as an internal thing, I have a
certain amount of control over things like browser and cpu, but the key
was for it to be faster and easier than the previous version, which
relied entirely on server side scripting and form submissions
(reloading the page every time a branch was expanded, etc.).

Anyway, thanks a lot for the help (everyone). Problem solved, and
rightly or wrongly, I think I understand JavaScript much better now.

Feb 13 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Jimmy Cerra | last post by:
I am a little confused how the memory for objects is allocated in JavaScript. David Flanagan, in "JavaScript: The Definitive Guide," states that each property of a class takes up memory space when...
6
by: Martin | last post by:
I'd like to be able to get the name of an object instance from within a call to a method of that same object. Is this at all possible? The example below works by passing in the name of the object...
8
by: Steve Neill | last post by:
Can anyone suggest how to create an arbitrary object at runtime WITHOUT using the deprecated eval() function. The eval() method works ok (see below), but is not ideal. function Client() { }...
26
by: yb | last post by:
Hi, Is there a standard for the global 'window' object in browsers? For example, it supports methods such as setInterval and clearInterval, and several others. I know that w3c standardized...
4
by: Daniel | last post by:
Hi, I was reading Douglas Crockford's article on prototypal inheritance at http://javascript.crockford.com/prototypal.html. I think it also relates to a post back in Dec 2005. The mechanism...
14
by: julie.siebel | last post by:
I've been wrestling with a really complex page. All the data is drawn down via SQL, the page is built via VBScript, and then controlled through javascript. It's a page for a travel company that...
1
by: Jean-Paul Calderone | last post by:
On Tue, 22 Apr 2008 14:54:37 -0700 (PDT), yzghan@gmail.com wrote: The test doesn't demonstrate any leaks. It does demonstrate that memory usage can remain at or near peak memory usage even after...
11
by: Are Nybakk | last post by:
Hi, I've stumbled into a problem I just can't figure out. I found out that variables in JS don't have local scope inside brackets in say, a loop, but things still doesn't add up. Also, the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.