Added benchmark data for privileged members under v8 (currently Figure 1)
parent
a670dbf2e0
commit
63083533dc
|
@ -7,6 +7,7 @@
|
|||
\usepackage{color}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{cite}
|
||||
\usepackage{multirow}
|
||||
|
||||
\hypersetup{colorlinks,
|
||||
citecolor=black,
|
||||
|
@ -21,6 +22,7 @@
|
|||
\definecolor{lightgray}{rgb}{0.6,0.6,0.6}
|
||||
|
||||
\newcommand{\jsref}{\textmd Listing~\ref}
|
||||
\newcommand{\fref}{\textmd Figure~\ref}
|
||||
|
||||
\lstdefinelanguage{JavaScript}{%
|
||||
keywords={%
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
function Foo( name )
|
||||
{
|
||||
this.getName = function()
|
||||
{
|
||||
return name;
|
||||
};
|
||||
|
||||
this.setName = function( newname )
|
||||
{
|
||||
name = newname;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Performance testing on an instance of Foo (rather specific, I know.
|
||||
* Lazy-programmer-who-wants-to-get-back-to-writing-his-article syndrome).
|
||||
*/
|
||||
|
||||
exports.run = function( Foo )
|
||||
{
|
||||
// get initial memory usage and start time in ms
|
||||
var mem = process.memoryUsage().heapUsed,
|
||||
start = ( new Date() ).getTime();
|
||||
|
||||
// instantiate a number of Foo's, keeping them in memory.
|
||||
var i = count = 1e6, a = [];
|
||||
while ( i-- )
|
||||
{
|
||||
a[i] = new Foo();
|
||||
}
|
||||
|
||||
// gather final statistics before doing any additional work
|
||||
var end = ( ( new Date() ).getTime() - start ),
|
||||
mem_end = ( process.memoryUsage().heapUsed - mem ),
|
||||
cstart = ( new Date() ).getTime();
|
||||
|
||||
i = count;
|
||||
while ( i-- )
|
||||
{
|
||||
a[0].getName();
|
||||
a[0].setName();
|
||||
};
|
||||
|
||||
var cend = ( ( new Date() ).getTime() - cstart );
|
||||
|
||||
return [ mem_end, end, cend ];
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Outputs the amount of time to run various tests against a protected member
|
||||
* implementation of Foo
|
||||
*/
|
||||
|
||||
function Foo( name )
|
||||
{
|
||||
this.getName = function()
|
||||
{
|
||||
return name;
|
||||
};
|
||||
|
||||
this.setName = function( newname )
|
||||
{
|
||||
name = newname;
|
||||
};
|
||||
}
|
||||
|
||||
console.log(
|
||||
require( './inst-call-cmp' ).run( Foo ).join( '\t' )
|
||||
);
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Outputs the amount of time to run various tests against a prototype
|
||||
* implementation of Foo
|
||||
*/
|
||||
|
||||
function Foo( name )
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Foo.prototype = {
|
||||
getName: function()
|
||||
{
|
||||
return this.name;
|
||||
},
|
||||
|
||||
setName: function( newname )
|
||||
{
|
||||
this.name = newname;
|
||||
},
|
||||
};
|
||||
|
||||
console.log(
|
||||
require( './inst-call-cmp' ).run( Foo ).join( '\t' )
|
||||
);
|
|
@ -216,23 +216,10 @@ that functions introduce scope, allowing us to define a local variable (or use
|
|||
an argument) within the constructor that is only accessible to the
|
||||
\dfn{privileged member} \func{getName()}.
|
||||
|
||||
\begin{lstlisting}[%
|
||||
\lstinputlisting[%
|
||||
label=lst:privileged,
|
||||
caption=Using privileged members to encapsulate data
|
||||
]
|
||||
function Foo( name )
|
||||
{
|
||||
this.getName = function()
|
||||
{
|
||||
return name;
|
||||
};
|
||||
|
||||
this.setName = function( newname )
|
||||
{
|
||||
name = newname;
|
||||
};
|
||||
}
|
||||
\end{lstlisting}
|
||||
]{lst/privileged-members.js}
|
||||
|
||||
If \var{name} in \jsref{lst:privileged} is encapsulated within the constructor,
|
||||
our methods that \emph{access} that encapsulated data must \emph{too} be
|
||||
|
@ -240,12 +227,39 @@ declared within the constructor;\footnote{One may mix prototypes and privileged
|
|||
members.} otherwise, if placed within the prototype, \var{name} would be out of
|
||||
scope. This implementation has an unfortunate consequence --- our methods are
|
||||
now being \emph{redeclared} each and every time a new instance of \var{Foo} is
|
||||
created, which has obvious performance penalties.\footnote{As a general rule
|
||||
of thumb, one should only use privileged members for methods that access
|
||||
encapsulated data; all other members should be part of the prototype.}
|
||||
created, which has obvious performance penalties (see
|
||||
\fref{fig:proto-priv-cmp}).\footnote{As a general rule of thumb, one should only
|
||||
use privileged members for methods that access encapsulated data; all other
|
||||
members should be part of the prototype.}
|
||||
|
||||
\begin{figure}
|
||||
\center
|
||||
\begin{tabular}{r|r|r|r|}
|
||||
\cline{2-4}
|
||||
& Heap Usage
|
||||
& \multicolumn{1}{|c|}{Inst. Time}
|
||||
& \multicolumn{1}{|c|}{Call Time} \\
|
||||
\hline
|
||||
\multicolumn{1}{|r|}{\jsref{lst:proto-proper}}
|
||||
& 49.7M & 234ms & 17ms \\
|
||||
\multicolumn{1}{|r|}{\jsref{lst:privileged}}
|
||||
& 236.0M & 1134ms & 28ms \\
|
||||
\hline
|
||||
\multicolumn{1}{|r|}{\% Change} & 374.8\% & 384.6\% & 64.7\% \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Comparing performance of privileged member and prototype
|
||||
implementations under v8. The heap usage column represents the
|
||||
heap usage after instantiating \var{Foo} under the respective implementation $n$
|
||||
times, and the Inst. CPU column reflects the amount of time spent instantiating
|
||||
the $n$ objects. The Call CPU column reflects the amount of time spent invoking
|
||||
\emph{each} member of \emph{one} instance $n$ times. $n = 1,000,000$. Lower
|
||||
numbers are better. Different environments may have different results.}
|
||||
\label{fig:proto-priv-cmp}
|
||||
\end{figure}
|
||||
|
||||
Due to these performance concerns, it is often undesirable to use privileged
|
||||
members; many developers will instead simply prefix with an underscore members
|
||||
members; many developers will instead prefix, with an underscore, members
|
||||
intended to be private (e.g. \code{this.\_name}) while keeping all methods on
|
||||
the prototype.\footnote{One example of a library that uses underscores in place
|
||||
of privileged members is Dojo at http://dojotoolkit.org.} This serves as a clear
|
||||
|
|
Loading…
Reference in New Issue