JavaScript: String Concatenation slow performance? Array.join('')? - javascript

I've read that if I have a for loop, I should not use string concation because it's slow. Such as:
for (i=0;i<10000000;i++) {
str += 'a';
}
And instead, I should use Array.join(), since it's much faster:
var tmp = [];
for (i=0;i<10000000;i++) {
tmp.push('a');
}
var str = tmp.join('');
However, I have also read that string concatention is ONLY a problem for Internet Explorer and that browsers such as Safari/Chrome, which use Webkit, actually perform FASTER is using string concatention than Array.join().
I've attempting to find a performance comparison between all major browser of string concatenation vs Array.join() and haven't been able to find one.
As such, what is faster and more efficient JavaScript code? Using string concatenation or Array.join()?

It appears Array.join() for the most part across browsers is faster.
Current gen Browsers
FF3 array.join is ~2x faster
Safari 3 array.join ~1.5x faster
Opera 9 += ~3x faster
ie6 array.join ~6x faster
ie7 array.join ~4x faster
Next gen browsers
FF3.1 += array.join equal in speed
Chrome += ~1.25x faster
IE8 array.join ~1.6x faster
Webkit array.join ~2x faster
Test results here: http://www.learningjquery.com/2009/03/43439-reasons-to-use-append-correctly

My feeling is that since there's no "nice" way to do a feature check to see whether string concatenation is slow, and because Array.join() is not terrible in non-IE browsers, using the array approach is good because your pages will behave pretty well everywhere and you won't have a mess to maintain (and you can avoid browser sniffing).
Now if you're implementing a framework or a library and not just a feature or two on a site, then more fine tuning might be called for.
Finally, I suggest going back to google and reading some of the results you get from a search for "javascript string concatenation performance." I found several good ones and I only got through half the first SRP. Read the comments on the blog posts too because often you pick up interesting links there.

I was curious not only about string concatenation, but about parsing as well. Here are some results regarding array.join, string+=, charAt() and array[].
Short summary
joining array is roughly 2.5-6 times quicker than string+=
array[] is 1.5-3 times quicker than charAt() (and splitting string to array is not an expansive operation)
Raw results
Chrome v23 FF 17 IE8
fill array(100k) 43 15 270 ms
join array(100k) 33 5 43 ms
string+=(100k) 223 12 118 ms
charAt(488.89k * 100) 517 462 75467 ms
split(488.89k) 12 34 279 ms
array[](488.89k * 100) 267 323 27343 ms
HTML code to test
<table>
<col/>
<col align="right"/>
<col/>
<script type="text/javascript" >
function test(what, action) {
var start = new Date(), end
document.write("<tr><td>" + what + "</td>")
action()
end = new Date()
document.write("<td>" + (end.getTime() - start.getTime()) + "</td> <td>ms</td></tr>\n")
}
var alen = 100000, efAlen, nIter = 100
var s = "" // test string for charAt, s[pos]
var ss = "" // subject ss += "??"
var as = [] // source for s = as.join("")
var slen // slen = s.length
var a // a = s.split("")
var maxSlen = 1000*1000
test("fill array(" + (alen / 1000) + "k)", function() {
slen = 0
for( var i = 0; i < alen; i++ ) {
var v = "" + i
slen += v.length
if( slen < maxSlen )
efAlen = (i + 1)
as[i] = v
}
})
test("join array(" + (efAlen / 1000) + "k)", function() {
s = as.slice(0, efAlen).join("")
slen = Math.min(s.length, maxSlen)
})
test("string+=(" + (efAlen / 1000) + "k)", function() {
for( var i = 0; i < efAlen; i++ ) {
ss += as[i]
}
if( ss != s )
document.write("ss.length:" + ss.length + ", s.length:" + s.length)
})
test("charAt(" + (slen / 1000) + "k * " + nIter + ")", function() {
for( var i = 0; i < nIter; i++ ) {
for( var p = 0; p < slen; p++ ) {
var c = s.charAt(p)
}
}
})
test("split(" + (slen / 1000) + "k)", function() {
a = s.split("")
})
test("array[](" + (slen / 1000) + "k * " + nIter + ")", function() {
for( var i = 0; i < nIter; i++ ) {
for( var p = 0; p < slen; p++ ) {
var c = a[p]
}
}
})
</script>
</table>

Related

How do I apply the conversion from charCodeAt to C # here?

So I've already found posts on this topic, but that didn't really help me. On the one hand, I have tried something like this, for example, but it is not quite right in my case**(C#)**.
string temp;
foreach (var a in chaine)
temp = ( Convert.ToUInt16(a).ToString("X4"));
for (j = 0; j < intlenght; j+= 1)
{
arrayData[j + 1] = temp;
}
Why I think it doesn't really work is that my starting form looked a little different than the examples and I'm not really familiar with JavaScript. My starting shape looks like this**(javaScript)**:
for (j = 0; j < intlenght; j+= 1)
{
arrayData[j + 1] = x.charCodeAt(j) - 32;
}
the x in this case it is actually
var x = document.getElementById ("textIn"). value;
but in my method I have a string return value instead of the X
so how can i correctly get the
arrayData [j + 1] = x.charCodeAt (j) - 32;
translate in c #. In the end I need this in my method for Code128 encoder
EDIT for better Understanding:
So I have a TextBlock in my window, but there is a text in it in a barcode 128 font. However, this barcode cannot yet be read. So what I want to do is add the additional characters of the barcode so that at the end you can scan this barcode with a scanning program. To do that I come across this Stack Overflow answer: https://stackoverflow.com/a/60363928/17667316
However, the problem was with the question that the code is in JavaScript and not in C #. Since I've only found solutions where it works with libaries and nuggets (which I want to work around) I tried to convert this javaScript code into C #. I come across lines like this(javaScript):
arrayData[j + 1] = x.charCodeAt(j) - 32;
I didn't find a solution to this as I did this Javascript code:
var buttonGen = document.getElementById("btnGen");
buttonGen.onclick = function () {
var x = document.getElementById("textIn").value;
var i, j, intWeight, intLength, intWtProd = 0, arrayData = [], fs;
var arraySubst = [ "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê" ];
/*
* Checksum Calculation for Code 128 B
*/
intLength = x.length;
arrayData[0] = 104; // Assume Code 128B, Will revise to support A, C and switching.
intWtProd = 104;
for (j = 0; j < intLength; j += 1) {
arrayData[j + 1] = x.charCodeAt(j) - 32; // Have to convert to Code 128 encoding
intWeight = j + 1; // to generate the checksum
intWtProd += intWeight * arrayData[j + 1]; // Just a weighted sum
}
arrayData[j + 1] = intWtProd % 103; // Modulo 103 on weighted sum
arrayData[j + 2] = 106; // Code 128 Stop character
chr = parseInt(arrayData[j + 1], 10); // Gotta convert from character to a number
if (chr > 94) {
chrString = arraySubst[chr - 95];
} else {
chrString = String.fromCharCode(chr + 32);
}
// Change the font-size style to match the drop down
fs = document.getElementsByTagName("option")[document.getElementById("selList").selectedIndex].value;
document.getElementById("test").style.fontSize = fs + 'px';
document.getElementById("check").innerHTML =
'Checksum = ' + chr + ' or character ' + // Make It Visual
chrString + ', for text = "' + x + '"';
document.getElementById("test").innerHTML =
'Ì' + // Start Code B
x + // The originally typed string
chrString + // The generated checksum
'Î'; // Stop Code
}
Can convert into a working C # code.

How can i make a loop that will show '-' mark x time iteration was? [duplicate]

In Perl I can repeat a character multiple times using the syntax:
$a = "a" x 10; // results in "aaaaaaaaaa"
Is there a simple way to accomplish this in Javascript? I can obviously use a function, but I was wondering if there was any built in approach, or some other clever technique.
These days, the repeat string method is implemented almost everywhere. (It is not in Internet Explorer.) So unless you need to support older browsers, you can simply write:
"a".repeat(10)
Before repeat, we used this hack:
Array(11).join("a") // create string with 10 a's: "aaaaaaaaaa"
(Note that an array of length 11 gets you only 10 "a"s, since Array.join puts the argument between the array elements.)
Simon also points out that according to this benchmark, it appears that it's faster in Safari and Chrome (but not Firefox) to repeat a character multiple times by simply appending using a for loop (although a bit less concise).
In a new ES6 harmony, you will have native way for doing this with repeat. Also ES6 right now only experimental, this feature is already available in Edge, FF, Chrome and Safari
"abc".repeat(3) // "abcabcabc"
And surely if repeat function is not available you can use old-good Array(n + 1).join("abc")
Convenient if you repeat yourself a lot:
String.prototype.repeat = String.prototype.repeat || function(n){
n= n || 1;
return Array(n+1).join(this);
}
alert( 'Are we there yet?\nNo.\n'.repeat(10) )
Array(10).fill('a').join('')
Although the most voted answer is a bit more compact, with this approach you don't have to add an extra array item.
An alternative is:
for(var word = ''; word.length < 10; word += 'a'){}
If you need to repeat multiple chars, multiply your conditional:
for(var word = ''; word.length < 10 * 3; word += 'foo'){}
NOTE: You do not have to overshoot by 1 as with word = Array(11).join('a')
The most performance-wice way is https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
Short version is below.
String.prototype.repeat = function(count) {
if (count < 1) return '';
var result = '', pattern = this.valueOf();
while (count > 1) {
if (count & 1) result += pattern;
count >>>= 1, pattern += pattern;
}
return result + pattern;
};
var a = "a";
console.debug(a.repeat(10));
Polyfill from Mozilla:
if (!String.prototype.repeat) {
String.prototype.repeat = function(count) {
'use strict';
if (this == null) {
throw new TypeError('can\'t convert ' + this + ' to object');
}
var str = '' + this;
count = +count;
if (count != count) {
count = 0;
}
if (count < 0) {
throw new RangeError('repeat count must be non-negative');
}
if (count == Infinity) {
throw new RangeError('repeat count must be less than infinity');
}
count = Math.floor(count);
if (str.length == 0 || count == 0) {
return '';
}
// Ensuring count is a 31-bit integer allows us to heavily optimize the
// main part. But anyway, most current (August 2014) browsers can't handle
// strings 1 << 28 chars or longer, so:
if (str.length * count >= 1 << 28) {
throw new RangeError('repeat count must not overflow maximum string size');
}
var rpt = '';
for (;;) {
if ((count & 1) == 1) {
rpt += str;
}
count >>>= 1;
if (count == 0) {
break;
}
str += str;
}
// Could we try:
// return Array(count + 1).join(this);
return rpt;
}
}
If you're not opposed to including a library in your project, lodash has a repeat function.
_.repeat('*', 3);
// → '***
https://lodash.com/docs#repeat
For all browsers
The following function will perform a lot faster than the option suggested in the accepted answer:
var repeat = function(str, count) {
var array = [];
for(var i = 0; i < count;)
array[i++] = str;
return array.join('');
}
You'd use it like this :
var repeatedString = repeat("a", 10);
To compare the performance of this function with that of the option proposed in the accepted answer, see this Fiddle and this Fiddle for benchmarks.
For moderns browsers only
In modern browsers, you can now do this using String.prototype.repeat method:
var repeatedString = "a".repeat(10);
Read more about this method on MDN.
This option is even faster. Unfortunately, it doesn't work in any version of Internet explorer. The numbers in the table specify the first browser version that fully supports the method:
In ES2015/ES6 you can use "*".repeat(n)
So just add this to your projects, and your are good to go.
String.prototype.repeat = String.prototype.repeat ||
function(n) {
if (n < 0) throw new RangeError("invalid count value");
if (n == 0) return "";
return new Array(n + 1).join(this.toString())
};
String.repeat() is supported by 96.39% of browsers as of now.
function pad(text, maxLength){
return text + "0".repeat(maxLength - text.length);
}
console.log(pad('text', 7)); //text000
/**
* Repeat a string `n`-times (recursive)
* #param {String} s - The string you want to repeat.
* #param {Number} n - The times to repeat the string.
* #param {String} d - A delimiter between each string.
*/
var repeat = function (s, n, d) {
return --n ? s + (d || "") + repeat(s, n, d) : "" + s;
};
var foo = "foo";
console.log(
"%s\n%s\n%s\n%s",
repeat(foo), // "foo"
repeat(foo, 2), // "foofoo"
repeat(foo, "2"), // "foofoo"
repeat(foo, 2, "-") // "foo-foo"
);
Just for the fun of it, here is another way by using the toFixed(), used to format floating point numbers.
By doing
(0).toFixed(2)
(0).toFixed(3)
(0).toFixed(4)
we get
0.00
0.000
0.0000
If the first two characters 0. are deleted, we can use this repeating pattern to generate any repetition.
function repeat(str, nTimes) {
return (0).toFixed(nTimes).substr(2).replaceAll('0', str);
}
console.info(repeat('3', 5));
console.info(repeat('hello ', 4));
Another interesting way to quickly repeat n character is to use idea from quick exponentiation algorithm:
var repeatString = function(string, n) {
var result = '', i;
for (i = 1; i <= n; i *= 2) {
if ((n & i) === i) {
result += string;
}
string = string + string;
}
return result;
};
For repeat a value in my projects i use repeat
For example:
var n = 6;
for (i = 0; i < n; i++) {
console.log("#".repeat(i+1))
}
but be careful because this method has been added to the ECMAScript 6 specification.
function repeatString(n, string) {
var repeat = [];
repeat.length = n + 1;
return repeat.join(string);
}
repeatString(3,'x'); // => xxx
repeatString(10,'🌹'); // => "🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹"
This is how you can call a function and get the result by the helps of Array() and join()
using Typescript and arrow fun
const repeatString = (str: string, num: number) => num > 0 ?
Array(num+1).join(str) : "";
console.log(repeatString("🌷",10))
//outputs: 🌷🌷🌷🌷🌷🌷🌷🌷🌷🌷
function repeatString(str, num) {
// Array(num+1) is the string you want to repeat and the times to repeat the string
return num > 0 ? Array(num+1).join(str) : "";
}
console.log(repeatString("a",10))
// outputs: aaaaaaaaaa
console.log(repeatString("🌷",10))
//outputs: 🌷🌷🌷🌷🌷🌷🌷🌷🌷🌷
Here is what I use:
function repeat(str, num) {
var holder = [];
for(var i=0; i<num; i++) {
holder.push(str);
}
return holder.join('');
}
I realize that it's not a popular task, what if you need to repeat your string not an integer number of times?
It's possible with repeat() and slice(), here's how:
String.prototype.fracRepeat = function(n){
if(n < 0) n = 0;
var n_int = ~~n; // amount of whole times to repeat
var n_frac = n - n_int; // amount of fraction times (e.g., 0.5)
var frac_length = ~~(n_frac * this.length); // length in characters of fraction part, floored
return this.repeat(n) + this.slice(0, frac_length);
}
And below a shortened version:
String.prototype.fracRepeat = function(n){
if(n < 0) n = 0;
return this.repeat(n) + this.slice(0, ~~((n - ~~n) * this.length));
}
var s = "abcd";
console.log(s.fracRepeat(2.5))
I'm going to expand on #bonbon's answer. His method is an easy way to "append N chars to an existing string", just in case anyone needs to do that. For example since "a google" is a 1 followed by 100 zeros.
for(var google = '1'; google.length < 1 + 100; google += '0'){}
document.getElementById('el').innerText = google;
<div>This is "a google":</div>
<div id="el"></div>
NOTE: You do have to add the length of the original string to the conditional.
Lodash offers a similar functionality as the Javascript repeat() function which is not available in all browers. It is called _.repeat and available since version 3.0.0:
_.repeat('a', 10);
var stringRepeat = function(string, val) {
var newString = [];
for(var i = 0; i < val; i++) {
newString.push(string);
}
return newString.join('');
}
var repeatedString = stringRepeat("a", 1);
Can be used as a one-liner too:
function repeat(str, len) {
while (str.length < len) str += str.substr(0, len-str.length);
return str;
}
In CoffeeScript:
( 'a' for dot in [0..10]).join('')
String.prototype.repeat = function (n) { n = Math.abs(n) || 1; return Array(n + 1).join(this || ''); };
// console.log("0".repeat(3) , "0".repeat(-3))
// return: "000" "000"

.append VS .html VS .innerHTML performance

This site's run a test between the 3 different methods and it seems .html is the fastest, followed by .append. followed by .innerHTML. Can someone explain to me the reasons why?
Here's the site which does the comparison among the three methods.
I have read this this SO question which is related but I don't really understand the given answer, and the question didn't really elaborate much regarding .innerHtml.
I don't understand the following part:
A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection.
Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass just <div></div> to jQuery(), jQuery will take a shortcut and simply do document.createElement('div').
Can someone simplify this?
All three are slow to me. Modifying the dom on each iteration is slow.
http://jsperf.com/jquery-append-vs-html-list-performance/24
I just added a new test in there:
var html = [];
for (var i = 0; i < len; i++) {
html.push('<div>Test ' + i + '</div>');
}
document.getElementById('list').innerHTML = html.join('');
This is much faster again. :)
My method in Firefox does 26k Ops/sec vs 1,000, 10,000, and 13
That benchmark is worthless. innerHTML is always faster than DOM manipulation.
jQuery seems faster because it prepares a string with all the HTML first while the others do one operation each iteration. Also note that jQuery.html() uses innerHTML whenever it can.
jQuery from benchmark
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
}
$('#list').html(html);
innerHTML from benchmark
var list = document.getElementById('list');
for (var i = 0; i < len; i++) {
list.innerHTML = list.innerHTML + '<div>Test ' + i + '</div>';
}
The test for innerHTML would be a lot faster if it was written like:
var list = document.getElementById('list');
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
}
list.innerHTML = html;
http://jsben.ch/#/yDvKH
How can .html be faster than .innerHTML when the .html is using .innerHTML with a lot of extra code? Here .html implementation in jQuery (taken directly from jQuery file).
html: function( value ) {
return jQuery.access( this, function( value ) {
var elem = this[0] || {},
i = 0,
l = this.length;
if ( value === undefined ) {
return elem.nodeType === 1 ?
elem.innerHTML.replace( rinlinejQuery, "" ) :
undefined;
}
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
!wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
value = value.replace( rxhtmlTag, "<$1></$2>" );
try {
for (; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if ( elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem, false ) );
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch(e) {}
}
if ( elem ) {
this.empty().append( value );
}
}, null, value, arguments.length );
}
As Bart said, innerHTML is always faster than DOM manipulation.
I was testing hyperHTML, so I thought I share my results. I didn't actually run my benchmarks in CodePen originally, and there is an interesting difference in that the jQuery times are much closer to innerHTML running in CodePen.
Chrome:
createFragment 312.80 ms
hyperHTML 253.10 ms
innerHTML 62.70 ms
$.append 183.40 ms
Chrome (extensions off):
createFragment 225.10 ms
hyperHTML 139.80 ms
innerHTML 47.80 ms
$.append 170.90 ms
Firefox:
createFragment 141 ms
hyperHTML 84 ms
innerHTML 25 ms
$.append 90 ms
Edge:
createFragment 422.50 ms
hyperHTML 184.60 ms
innerHTML 44.00 ms
$.append 1629.69 ms
IE11:
createFragment 1180.29 ms
hyperHTML 13315.59 ms //slow fallbacks, IE sucks
innerHTML 125.70 ms
$.append 2382.49 ms
I think it is all pretty simple. JavaScript is not as fast as the browser at parsing and creating elements, because the browser is machine specific compiled code. You can't do better than just handing over the HTML and letting the browser do the work without interruption.
It is possible that some of the performance differences are due to XSS checking, which would seem prudent.
function runbench(){
var data = [];
for (var i = 0; i < 10001; i++) {
data.push("<span>" + i + "</span>");
}
var perf=[];
var t0 = performance.now();
var c = document.createDocumentFragment();
for (var i = 0; i < 10001; i++) {
var e = document.createElement("span");
e.innerHTML = data[i];
c.appendChild(e);
}
document.querySelector('#createFragment').appendChild(c);
document.querySelector('#createFragment').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
document.querySelector('#innerHTML').innerHTML = data.join('');
document.querySelector('#innerHTML').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
$('#jqhtml').html(data.join(''));
document.querySelector('#jqhtml').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
$('#jqappend').append(data.join(''));
document.querySelector('#jqappend').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var t0 = performance.now();
hyperHTML.bind(document.querySelector('#hyperHTML'))
`${data.map(function (item) {
return "<span>" + item + "</span>";
})}`;
document.querySelector('#hyperHTML').classList='done';
var t1 = performance.now();
perf.push(t1-t0);
var stats = [];
stats.push("<table>")
stats.push("<tr><td>createFrag: </td><td>" + perf[0].toFixed(2) + "</td></tr>");
stats.push("<tr><td>innerHTML: </td><td>" + perf[1].toFixed(2) + "</td></tr>");
stats.push("<tr><td>$.html: </td><td>" + perf[2] .toFixed(2) + "</td></tr>");
stats.push("<tr><td>$.append: </td><td>" + perf[3] .toFixed(2) + "</td></tr>");
stats.push("<tr><td>hyperHTML: </td><td>" + perf[4].toFixed(2) + "</td></tr>");
stats.push("</table>");
$('#performance').html(stats.join(''));
document.querySelector('#performance').classList='done';
}
https://codepen.io/jwhooper/pen/GzKwMV
I think the innerHTML is faster with suggesstion #Brat.
And on creating loop and appending string should be good on using variable first.
It is make your performance more good.
good code:
var html = '';
for (var i = 0; i < len; i++) {
html += '<div>Test ' + i + '</div>';
};
$('#list').append(html);
not efficient code:
for (var i = 0; i < len; i++) {
var html = '<div>Test ' + i + '</div>';
$('#list').append(html);
}
for example: http://jsben.ch/#/yDvKH
I also had a problem with big table redraw (about 10x100 size). It takes about 300ms to redraw whole table.
The reason was not in the jQuery.append() and not in dom.innerHTML, but in appending each element each time.
The fastest way is to concatenate all elements html code and then append it to DOM.
Like this:
function redrawMyTable( myData )
{
var innerHTML = '';
for ( var i = 0; i < myData.length; i++ )
{
innerHTML += createRowFromData( myData[i] );
}
myTableTbody.innerHTML = innerHTML;
}
function createRowFromData( rowData )
{
var rowHTML = '';
for ( var i = 0; i < rowData.length; i++ )
{
rowHTML += createCellFromData( rowData[i] );
}
return rowHTML;
}
function createCellFromData( cellData )
{
//Do everything you need, and return HTMl code as a string
return cellHTML;
}
Now it takes only 20-30 ms (against 300ms :))
6 years later
Point is - don't manipulate the live DOM. Do it outside. Today, it doesn't matter where. You can use a HTML String, a DocumentFragment (which excludes Internet Explorer) or create a new Element but don't add it to the DOM, fill it as you need and THEN add it.
On Chrome and Firefox my observation is that it's all the same run time, give or take a few percent.
Building a long HTML String in chunks that are stored in an array and then join('')-ed is also not necessary any more. Years ago, I measured big time differences. Not today. Point one: there's no recognizable time difference (on Chrome and FF), and point two: the time isn't lost at this point, but in rendering.
my code innerHTML vs fragment
fragment use
running time : 1300~1500ms
innerHTML use
running time : 1800~2000ms
`
const data = [];
for(let i = 0; i < 1000001;i++){
data.push(i);
}
function useInnerHtml(result_wrap){
let text = ''
for(const item of data){
text += '<div>' + item + '</div>';
}
result_wrap.innerHTML = text;
}
function useFragment(result_wrap){
const fragment= new DocumentFragment(); // or document.createDocumentFragment();
for(const item of data){
const div = document.createElement('div');
div.textContent = item;
fragment.appendChild(div);
}
result_wrap.appendChild(fragment);
}
function createData(obj){
let startTime = new Date().getTime();
const targetParentNode = obj.parentNode;
const result_wrap = targetParentNode.querySelector('.result-wrap');
if(result_wrap.hasChildNodes() == false){
if(result_wrap.className.includes('inner-html')){
useInnerHtml(result_wrap);
}else if(result_wrap.className.includes('fragment')){
useFragment(result_wrap, targetParentNode);
}else{
alert('');
}
}else{
alert('click remove button');
}
let endTime = new Date().getTime();
let time = (endTime - startTime);
targetParentNode.querySelector('.running-time').textContent = 'running time : ' + time + 'ms'
}
function removeContent(){
[...document.querySelectorAll('.result-wrap')].map(e=>e.replaceChildren());
}
`
https://codepen.io/joohyoungkim19940805/pen/BaJQeGW

Why is a custom array reverse implementation twice as fast versus .reverse() in V8

A simple implementation for reversing an array is twice as fast compared to the built in function in Javascript, when tested in Chrome. What's V8 doing? Here is the test:
var newArr = [];
var newArrDefault = [];
for(var i = 0; i < 10000000; i++){
newArr[i] = i;
newArrDefault[i] = i;
}
var startDefault = new Date();
newArrDefault.reverse();
console.log("Built in method took " + (new Date().getTime() - startDefault.getTime()));
var start = new Date();
for(var i = 0; i < newArr.length / 2; i++){
var tmp = newArr[i];
newArr[i] = newArr[newArr.length-i-1];
newArr[newArr.length-i-1] = tmp;
}
console.log("Custom method took " + (new Date().getTime() - start.getTime()));
Results on Version 20.0.1132.47 Ubuntu 12.04 (144678):
Built in method took 149
Custom method took 71
For the fun of it, I implemented the specification like so:
var upper, upperExists, lowerExists, lowerValue, upperValue;
for(var lower = 0, len = newArr.length >>> 0, middle = Math.floor(len / 2); lower != middle; ++lower) {
upper = len - lower - 1;
lowerValue = newArr[lower];
upperValue = newArr[upper];
lowerExists = newArr.hasOwnProperty(lower);
upperExists = newArr.hasOwnProperty(upper);
if (lowerExists && upperExists) {
newArr[lower] = upperValue;
newArr[upper] = lowerValue;
} else if (upperExists) {
newArr[lower] = upperValue;
delete newArr[upper];
} else if (lowerExists) {
newArr[upper] = lowerValue;
delete newArr[lower];
}
}
The jsperf can be found here.
It includes a whole bunch of code to deal with missing entries, which is why it's so much slower than both the native and your code (some optimizations may be possible, but it won't affect the performance enough). The performance difference between your code and the native implementation wasn't very conclusive though.
Under most circumstances arrays are a contiguous block of values with no gaps in between, so you should be safe with that kind of code; as long as you know the difference :)

(P)RNG - Array of Random Numbers Created with a Seed

I want to create an array of random/pseudo-random numbers using a seed. I want the very same array to be created when the same seed is used and I want to have little or no visible pattern in the array. I'm working in JavaScript.
This is the random function I'm using, which I'm quite happy with (sorry, I forgot who the original author is):
function random(seed) {
if (!seed) seed = new Date().getTime();
seed = (seed*9301+49297) % 233280;
return seed/(233280.0);
}
This is the array generation:
var superSeed = random();
var nRandom = 100;
var randomArray = new Array();
for (var i = 0 ; i < nRandom ; i++){
randomArray.push(random((superSeed*10)+ (i)));
}
Somehow the pattern seems to be quite similar, no matter how often I run it. This question seems to be similar, but since it's about matrixes, I don't understand what's being said.
Thanks!
Having worked on similar things before I think we can use a fairly simple series, which takes two initial values and then you can get a lot more.
var a1,b1;
function InitSequence(v1, v2) {
a1 = Math.pow(v1, 5) / Math.pow(v1, 3);
b1 = Math.pow(v2, 8);
lastrand = (a1 + b1) & 0x7fffffff;
}
function SequenceNext() {
var alast = a1;
var nextVal = (a1 + b1) & 0x7fffffff;
b1 = alast;
a1 = nextVal;
return nextVal;
}
Then use it like this:
InitSequence(75, 21);
for (var i = 0; i < 99; i++) {
v = SequenceNext();
}
I tested it like this:
var used = new Array();
InitSequence(75, 21); // any two values will do.
// fill 10k into array.
for (var i = 0; i < 9999; i++) {
v = SequenceNext();
if (undefined != used[v]) {
used[v]++;
} else used[v] = 1;
//document.write(i+": "+v+"<br>");
}
// see if there any duplicates.
var tdup = 0;
for (xx in used) {
ndup = used[xx];
if (ndup > 1) {
document.write("duplicated " + xx + " :" + ndup + "<br>");
tdup += ndup;
}
}
document.write("Total dups " + tdup + "<br>");
This is using the Fibonacci series, which in mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
. I'm starting with different values - (v1^5) / (v1^3) and v2 ^ 8; otherwise it would only ever be identical.
I like the "Super 7" PRNG. It is simple, fast (although the other answer with the fib. sequence is fast as well), and has the interesting property:
In the entire range -- albeit of a meager of 32k -- there are no duplicates using the "Super 7" PRNG.
Multiple 7's can be joined to increase the number of bits and/or provide multiple seeds. This non-duplication property can exposed or folded.
(The sequence of a PRNG is always the same given a starting seed: it's the distribution and cycle lengths that are interesting -- it is these properties that may make them ideal in different cases where "true randomness" isn't desired).
Happy coding.
Maybe you should try this
function s_random() {
s_random.m = 71402523; s_random.a = 409647; s_random.c = 1508892;
s_random.seed = (s_random.seed*s_random.a + s_random.c) % s_random.m;
return s_random.seed / s_random.m;
}
/*
generate IV
s_random.seed = Math.floor((new Date).getTime()/10000);
*/
s_random.seed = 130324232;
var CheckRandom = 4999999;
var PrintSamples = 100;
var used = new Array();
for (var i = 0; i < CheckRandom; i++) {
v = (Math.ceil(Math.sqrt(s_random())* 1000000000) * 8);
if (undefined != used[v]) {
used[v]++;
} else used[v] = 1;
if ( i< PrintSamples) document.write(i+": "+v+"");
}
/* see if there are any duplicates. */
var tdup = 0;
for (xx in used) {
ndup = used[xx];
if (ndup > 1) {
if (ndup < PrintSamples) document.write("duplicated " + xx + " :" + ndup + "");
tdup += ndup;
}
}
document.write("Total generated " + CheckRandom + "");
document.write("Total duplicates " + tdup + "");
Just got 5 million seeded, repeatable random numbers and no duplicates. Tested several times on Mac OS X with Safari.
Cheers,
Karl

Categories

Resources