I alle tests vil vi med et loop oprette X antal elementer og så indsætte dem i DOM’en. Jeg har til hver test oprettet en metode til håndtering af testen. De følgende kodeeksempler er skåret ned til det essentielle. Sidst i posten kan den samlede testkode dog læses.
Til alle jQuery.append() tests har jeg valgt at benytte mig af html tagget dl (Datalist) da den passer udemærket til formålet. Eftersom resultatet helt sikkert vil variere fra computer til computer og imellem browsere, skal man selv køre testen her på sitet. Som standard indsættes 1000 elementer, men jeg har gjort det muligt for jer, selv at vælge antallet af elementer.
JQuery.append() testen vil starte med at indsætte det valgte antal elementer og derefter gøre det samme med halvt så mange elementer. Den vil så halvere antallet af elementer indtil der kun indsættes et enkelt. På den måde får man en række konkrete data listet overskueligt i en tabel. Alle tests er kædet sammen og starter med lille mellemrum.
For at teste indsættelse af både store og små elementer har jeg delt testen op i to. Den første del indsætter helt simple, tomme html dl elementer. Den anden indsætter mere avancerede dl elementer, med både indhold og attributter.
Løsningsmuligheder
Vi forudsætter at vi skal have oprettet en række javascript DOM elementer, som så skal sættes ind som child elementer til et allerede eksisterende DOM element. Vi skal have fundet den mest optimale procedure og vi skal i øvrigt kunne forsøge os med et flexibelt antal elementer.Jeg vil i alle tests referere til elementet “insertIntoEle”, som det element vi ønsker at indsætte vores autogenererede DOM elementer i. InsertIntoEle vil i alle tests være det samme og jeg vil inden hver test begynder sørge for at rydde det for tidligere indsatte elementer. På den måde forventer jeg at denne del af testen ikke vil kunne have indflydelse på resultatet.
UPDATE: Jeg har nu udvidet testen så man også kan undersøge hvordan append fungerer UDEN oprettelse af elementer. Jeg har altså, i to nye serier af tests helt fjernet, den tid det tager at oprette elementerne fra ligningen.
Test 1: Indsætte elementer efterhånden som de bliver oprettet
Denne test vil benytte “document.createElement” metoden til at oprette de nye elementer. Før hver ny append selectes insertIntoEle ud af DOM’en.UPDATE: Alle eksempler er nu udvidet med en ny testfunktion, som viser hvordan jeg benytter append uden at oprette elementerne. Alle elementer er altså oprettet udenfor selve testen, men kun i de nye testserier. De to gamle fungerer som de hele tiden har gjort.
Denne test vil blive udført i følgende rækkefølge:
- Oprette et nyt element
- Selecte insertIntoEle
- Appende til insertIntoEle
- Gentage 1, 2 og 3 indtil vi har oprettet og indsat alle elementer
Javascript til test 1
//Simpel test
function (numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(createSimpleEle(i));
}
}
//Avanceret test
function (numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(createAdvancedEle(i));
}
}
//UPDATE: Simple and advanced no elements creation
function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(preCreatedElements[i]);
}
}
//createAdvancedEle() metoden
function createAdvancedEle(i) {
var newEle = jQuery(document.createElement("dd"));
newEle.html('Some text followed by a link <a href="http://rune.gronkjaer.dk"<Runes blog</a<')
.attr("id", "eleID" + i)
.attr("someWeirdAttribute", "someWeirdAttributeContent")
.addClass("eleClass");
return newEle;
}
//createSimpleEle() metoden
function createSimpleEle(i, createHtml) {
var newEle;
if (createHtml) {
newEle = '<dd></dd>';
} else {
newEle = jQuery(document.createElement("dd"));
}
return newEle;
}
Test 2: Som i test 1 men med cache
Jeg vil i denne test gemme insertIntoEle, som skal genbruges fra gang til gang. Jeg formoder at dette vil speede processen voldsomt op. I denne test vil jeg gøre det i følgende rækkefølge:- Oprette et element af gangen
- Selecte det element, der skal indsættes i, og gemme den i en variabel
- Appende vores insertIntoEle
- Gentage 1 og 3 indtil vi har oprettet og indsat alle elementer
Javascript til test 2
//Simpel test
function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
insertIntoEle.append(createSimpleEle(i));
}
}
//Avanceret test
function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
var newEle = jQuery(document.createElement("dd"));
insertIntoEle.append(createAdvancedEle(i));
}
}
//UPDATE: Simple and advanced no elements creation
function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
insertIntoEle.append(preCreatedElements[i]);
}
}
Test 3: Oprette midlertiddig container
Her skal testes muligheden for at oprette et midlertidigt container element, som alle nye elementer først indsættes i. Til slut vil jeg så appende containerens children til insertIntoEle. Teorien skulle være at den midlertidige container speeder processen op, da den udelukkende findes i computerens hukommelse, og altså ikke i DOM'en. Det er dog lidt et skud i tågen, da det ligeså godt kan blive langsommere af denne fremgangsmåde. I denne test vil jeg gøre det i følgende rækkefølge:- Oprette det midlertidige container element
- Oprette et element af gangen
- Appende den midlertidige container
- Gentage 2 og 3 indtil vi har oprettet og indsat alle elementer
- Appende alle containerens children til insertIntoEle
Javascript til test 3
//Simpel test
function (insertIntoEle, numberOfElements) {
var ele = null, jQContainer = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
ele = createSimpleEle(i);
jQContainer.append(ele);
}
insertIntoEle.append(jQContainer.children());
}
//Avanceret test
function (insertIntoEle, numberOfElements) {
var ele = null, jQContainer = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
jQContainer.append(createAdvancedEle(i));
}
insertIntoEle.append(jQContainer.children());
}
//UPDATE: Simple and advanced no elements creation
function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements.children());
}
Test 4: Skrive til en string og appende den til sidst
Denne test er meget simpel. Jeg konkatenerer alle elementer sammen til en lang html string, som til sidst appendes til insertIntoEle. Jeg formoder at jQuery skal bruge en masse tid på at parse string'en, og at denne metode vil være langsom. I denne test vil jeg gøre det i følgende rækkefølge:- Oprette en string
- Oprette et element af som en string
- Konkatenere elementet til stringen
- Gentage 2 og 3 indtil vi har oprettet alle elementer
- Appende string'en til insertIntoEle
Javascript til test 4
//Simpel test
function (insertIntoEle, numberOfElements) {
var ele = "";
for (var i = 0; i < numberOfElements; i++) {
ele += createSimpleEle(i, true);
}
insertIntoEle.append(ele);
}
//Avanceret test
function (insertIntoEle, numberOfElements) {
var ele = "";
for (var i = 0; i < numberOfElements; i++) {
ele += '<dd id="eleID' + i + '" class="eleClass"<Some text followed by a link<a href="http://rune.gronkjaer.dk"<Runes blog</a<</dd<';
}
insertIntoEle.append(ele);
}
//UPDATE: Simple and advanced no elements creation
function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
}
Test 5: Udnytte at jQuery er et array med jQuery.add() metoden
Denne test bygger på at jQuery objectet i bund og grund er et array af elementer. Med jQuery.add() metode kan man tilføje elementer til en samling, og her skal den så benyttes til at tilføje de nye elementer til vores container samling I denne test vil jeg gøre det i følgende rækkefølge:- Oprette et tomt jQuery objekt
- Oprette et element
- Tilføje elementet til jQuery objektet med jQuery.add()
- Gentage 2 og 3 indtil vi har oprettet og indsat alle elementer
- Appende den nu fyldte jQuery samling til insertIntoEle
Javascript til test 5
//Simpel test
function (insertIntoEle, numberOfElements) {
var ele = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
ele = ele.add(createSimpleEle(i));
}
insertIntoEle.append(ele);
}
//Avanceret test
function (insertIntoEle, numberOfElements) {
var ele = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
ele = ele.add(createAdvancedEle(i));
}
insertIntoEle.append(ele);
}
//UPDATE: Simple and advanced no elements creation
function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
}
Test med simple elementer
Antal elementer:
Antal elementer:
Vær opmærksom på at denne test kan tage længere tid da der indsættes elementer med både atributter og indhold.
Antal elementer:
| Antal elementer | T1: Normal | T2: Normal med cache | T3: Et append | T4: HTML append | T5: Tomt jQuery objekt |
Test med avancerede elementer
Vær opmærksom på at denne test kan tage længere tid da der indsættes elementer med både atributter og indhold.Antal elementer:
| Antal elementer | T1: Normal | T2: Normal med cache | T3: Et append | T4: HTML append | T5: Tomt jQuery objekt |
UPDATE: Test med simple elementer - fratrukket elementopretteles
I denne test laver vi elementerne uden for selve testen. Det vil sige at vi her KUN måler den tid det tager for selve append() om at udføre opgaven. Antal elementer:| Antal elementer | T1: Normal | T2: Normal med cache | T3: Et append | T4: HTML append | T5: Tomt jQuery objekt |
UPDATE: Test med avancerede elementer - fratrukket elementopretteles
I denne test laver vi elementerne uden for selve testen. Det vil sige at vi her KUN måler den tid det tager for selve append() om at udføre opgaven.Vær opmærksom på at denne test kan tage længere tid da der indsættes elementer med både atributter og indhold.
Antal elementer:
| Antal elementer | T1: Normal | T2: Normal med cache | T3: Et append | T4: HTML append | T5: Tomt jQuery objekt |
Konklusion
Overraskende nok er den klare vinder test nr. 3, html metoden. I de fleste tilfælde performer den klart bedre end konkurrenterne. Men prøv det lige selv. Der er kæmpe forskel på valget af browser og computer, hvilket også er ret spændende at teste. Det er også værd at bemærke, at selvom indsættelse af mere avanceret html er langsomere, så er det ikke meget langsommere. Man kan altså roligt indsætte også meget større klumper kode, hvis blot man benytter den rigtige metode.Jeg håber at folk kan bruge testen til noget, jeg har i hvert fald lært en del. Kom endelig med ideer, hvis jeg skal undersøge andre optimeringsmuligheder.
Hele koden
UPDATE: Koden er nu opdateret, så man kan se hvordan jeg udfører de to nye testserier. Det er bestemt ikke kønt mere, men det virker.Javascript - Hele testkoden
var testIsRunning = false, preCreatedElements = [];
jQuery(function () {
//Binding the event witch will start the simple test
jQuery("#runTests").click(function () {
//Henter antal
if (!testIsRunning) {
testIsRunning = true;
var numberOfElements = parseInt(jQuery("#numberOfElements").val());
runAllTests(numberOfElements, "appendTests", "resultsTable");
}
});
//Binding the event witch will start the advanced test
jQuery("#runAdvancedTests").click(function () {
if (!testIsRunning) {
testIsRunning = true;
var numberOfElements = parseInt(jQuery("#numberOfElementsAdvanced").val());
runAllTests(numberOfElements, "advancedAppendTests", "advancedResultsTable");
}
});
//Binding the event witch will start the advanced test
jQuery("#runTestsNoEleCreation").click(function () {
if (!testIsRunning) {
testIsRunning = true;
var numberOfElements = parseInt(jQuery("#numberOfElementsNoEleCreation").val());
runAllTests(numberOfElements, "appendTestsNoEleCreation", "resultsTableNoEleCreation", true);
}
});
//Binding the event witch will start the advanced test
jQuery("#runAdvancedTestsNoEleCreation").click(function () {
if (!testIsRunning) {
testIsRunning = true;
var numberOfElements = parseInt(jQuery("#numberOfElementsAdvancedNoEleCreation").val());
runAllTests(numberOfElements, "advancedAppendTestsNoEleCreation", "advancedResultsTableNoEleCreation", true);
}
});
});
/*
* Starts all tests of a certain type
*/
function runAllTests(numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
//The results table is cleared
jQuery('#' + resultsTableID + ' tr:not(:first)').remove();
//A Timeout secures the stability of the tests as the browsers will treat each test as a new process with its's own timeout period
window.setTimeout('initializeTest(' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Initialises a series of tests with a given number of elements to create
*/
function initializeTest(numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
var testResultTable = jQuery('#' + resultsTableID),
currentTr = testResultTable.find("tr:last"),
timeTaken = -1;
//Starts the new table row
currentTr = jQuery(document.createElement("tr"));
currentTr.append('<td>' + numberOfElements + '</td>');
testResultTable.append(currentTr);
//Readies the first test in the series in a timeout
window.setTimeout('runTest("test01", ' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Runs a test and then readies the next test
*/
function runTest(createMethodName, numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
if (preCreateElements) {
preCreatedElements = window[testMethodsName + "PreCreate"][createMethodName](numberOfElements);
var t = preCreatedElements;
}
var testResultTable = jQuery('#' + resultsTableID),
currentTr = testResultTable.find("tr:last"),
timeTaken = -1,
insertIntoEle = jQuery("#insertIntoEle .insertIntoEle").html(""),
startTime = (new Date()).getTime();
//Gets the current set of tests (Simple or advanced)
testMethods = window[testMethodsName];
//Runs the current test
testMethods[createMethodName](insertIntoEle, numberOfElements)
//Clocks the runtime of the test
timeTaken = (new Date()).getTime() - startTime;
//Appends the test result to the test restult table
currentTr.append('<td result="' + timeTaken + '">' + timeTaken + ' ms</td>');
var currentMethodFound = false;
//Find the next test
for (methodName in testMethods) {
if (currentMethodFound) {
//The next test is found and is now being readied to run
window.setTimeout('runTest("' + methodName + '", ' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
return;
}
//Checks to find the current test
currentMethodFound = methodName === createMethodName;
}
//If we get to this point, no more tests can be run
//Mark the looser and winner tests in the test result table
markWinnerResult(resultsTableID);
//If the number of elements have been counted down to 1, no mores tests can be run
if (numberOfElements === 1) {
testIsRunning = false;
return;
}
//Number of elements is halved for the next test series
numberOfElements = Math.ceil(numberOfElements / 2);
//Next test series initialization is readied
window.setTimeout('initializeTest(' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Below starts the actual tests
*/
//Two arrays are created to hold the variable number of tests
var appendTests = [],
advancedAppendTests = [],
appendTestsNoEleCreation = [],
appendTestsNoEleCreationPreCreate = [],
advancedAppendTestsNoEleCreation = [],
advancedAppendTestsNoEleCreationPreCreate = [];
//Simple test 1
appendTests["test01"] = function test01(insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(createSimpleEle(i));
}
};
//Simple test 2
appendTests["test02"] = function test02(insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
insertIntoEle.append(createSimpleEle(i));
}
};
//Simple test 3
appendTests["test03"] = function test03(insertIntoEle, numberOfElements) {
var ele = null, jQContainer = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
ele = createSimpleEle(i);
jQContainer.append(ele);
}
insertIntoEle.append(jQContainer.children());
};
//Simple test 4
appendTests["test04"] = function (insertIntoEle, numberOfElements) {
var ele = "";
for (var i = 0; i < numberOfElements; i++) {
ele += createSimpleEle(i, true);
}
insertIntoEle.append(ele);
};
//Simple test 5
appendTests["test05"] = function (insertIntoEle, numberOfElements) {
var ele = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
ele = ele.add(createSimpleEle(i));
}
insertIntoEle.append(ele);
};
//Advanced test 1
advancedAppendTests["test01"] = function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(createAdvancedEle(i));
}
};
//Advanced test 2
advancedAppendTests["test02"] = function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
var newEle = jQuery(document.createElement("dd"));
insertIntoEle.append(createAdvancedEle(i));
}
};
//Advanced test 3
advancedAppendTests["test03"] = function (insertIntoEle, numberOfElements) {
var ele = null, jQContainer = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
jQContainer.append(createAdvancedEle(i));
}
insertIntoEle.append(jQContainer.children());
};
//Advanced test 4
advancedAppendTests["test04"] = function (insertIntoEle, numberOfElements) {
var ele = "";
for (var i = 0; i < numberOfElements; i++) {
ele += createAdvancedEle(i, true);
}
insertIntoEle.append(ele);
};
//Advanced test 5
advancedAppendTests["test05"] = function (insertIntoEle, numberOfElements) {
var ele = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
ele = ele.add(createAdvancedEle(i));
}
insertIntoEle.append(ele);
};
/********************************************************************************************/
//Simple NoEleCreation test 1
appendTestsNoEleCreation["test01"] = function test01(insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(preCreatedElements[i]);
}
};
appendTestsNoEleCreationPreCreate["test01"] =
appendTestsNoEleCreationPreCreate["test02"] = function test01(numberOfElements) {
preCreatedElements = [];
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements.push(createSimpleEle(i));
}
return preCreatedElements;
};
//Simple NoEleCreation test 2
appendTestsNoEleCreation["test02"] = function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
insertIntoEle.append(preCreatedElements[i]);
}
};
//Simple NoEleCreation test 3
appendTestsNoEleCreation["test03"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements.children());
};
appendTestsNoEleCreationPreCreate["test03"] = function test01(numberOfElements) {
var ele = null, preCreatedElements = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements.append(createSimpleEle(i));
}
return preCreatedElements;
};
//Simple NoEleCreation test 4
appendTestsNoEleCreation["test04"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
};
appendTestsNoEleCreationPreCreate["test04"] = function (numberOfElements) {
preCreatedElements = "";
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements += createSimpleEle(i, true);
}
return preCreatedElements;
};
//Simple NoEleCreation test 5
appendTestsNoEleCreation["test05"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
};
appendTestsNoEleCreationPreCreate["test05"] = function (numberOfElements) {
preCreatedElements = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements = preCreatedElements.add(createSimpleEle(i));
}
return preCreatedElements;
};
//Advanced NoEleCreation test 1
advancedAppendTestsNoEleCreation["test01"] = function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(preCreatedElements[i]);
}
};
advancedAppendTestsNoEleCreationPreCreate["test01"] =
advancedAppendTestsNoEleCreationPreCreate["test02"] = function (numberOfElements) {
preCreatedElements = [];
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements.push(createAdvancedEle(i));
}
return preCreatedElements;
};
//Advanced NoEleCreation test 2
advancedAppendTestsNoEleCreation["test02"] = function (insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
insertIntoEle.append(preCreatedElements[i]);
}
};
//Advanced NoEleCreation test 3
advancedAppendTestsNoEleCreation["test03"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements.children());
};
advancedAppendTestsNoEleCreationPreCreate["test03"] = function (numberOfElements) {
var ele = null, preCreatedElements = jQuery("<dl>");
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements.append(createAdvancedEle(i));
}
return preCreatedElements;
};
//Advanced NoEleCreation test 4
advancedAppendTestsNoEleCreation["test04"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
};
advancedAppendTestsNoEleCreationPreCreate["test04"] = function ( numberOfElements) {
preCreatedElements = "";
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements += createAdvancedEle(i, true);
}
return preCreatedElements;
};
//Advanced NoEleCreation test 5
advancedAppendTestsNoEleCreation["test05"] = function (insertIntoEle, numberOfElements) {
insertIntoEle.append(preCreatedElements);
};
advancedAppendTestsNoEleCreationPreCreate["test05"] = function (numberOfElements) {
preCreatedElements = jQuery([]);
for (var i = 0; i < numberOfElements; i++) {
preCreatedElements = preCreatedElements.add(createAdvancedEle(i));
}
return preCreatedElements;
};
/********************************************************************************************/
//A method for creating the advanced elements. This ensures that they are alike every time.
function createAdvancedEle(i, createHtml) {
var newEle;
if (createHtml) {
newEle = '<dd id="eleID' + i + '" class="eleClass">Some text followed by a link<a href="http://rune.gronkjaer.dk">Runes blog</a></dd>';
} else {
newEle = jQuery(document.createElement("dd"));
newEle.html('Some text followed by a link <a href="http://rune.gronkjaer.dk">Runes blog</a>')
.attr("id", "eleID" + i)
.attr("someWeirdAttribute", "someWeirdAttributeContent")
.addClass("eleClass");
}
return newEle;
}
//A method for creating the simple elements. This ensures that they are alike every time.
function createSimpleEle(i, createHtml) {
var newEle;
if (createHtml) {
newEle = '<dd></dd>';
} else {
newEle = jQuery(document.createElement("dd"));
}
return newEle;
}
//Helping method for marking the winning and loosing test of each test series
function markWinnerResult(resultsTableID) {
var winner = -1, looser = -1, results = jQuery('#' + resultsTableID + ' tr:last td:not(:first)');
for (var i = 0; i < results.length; i++) {
var thisResult = parseInt(jQuery(results[i]).attr("result"));
if (winner === -1 || winner > thisResult) {
winner = thisResult;
}
if (looser < thisResult) {
looser = thisResult;
}
}
results.filter("[result=" + winner + "]").addClass("winner");
results.filter("[result=" + looser + "]").addClass("looser");
}
English version 

7 kommentarer
Hej Rune,
Pisse fedt og ikke mindst interessant indlæg! En af de metoder, som er lækkert at se dokumenteret.
Kan du komme nærmere ind på hvorfor test 4 ifht. test 3 er knapt 2,5x hurtigere v. brug af traditionel string konkatenering vs. jQuery appending? Noget af tiden skyldes selvfølgelig createAdvancedEle(), men hvad er forskellen i tid mellem selve sammenlægningerne?
- Allan
Altså trække den tid, som bruges på createAdvancedEle(), fra ligningen? Det vil jeg lige se om jeg kan finde tid til. Mit bud er jo at det ikke har nogen indflydelse, da den del burde gå ret hurtigt. Men det må da lige komme an på en prøve. Jeg har i hvert fald noteret det på min lille blogtodo.
/Rune
Dine hastigheds-tests holder ikke. Udfra hvad jeg kan se (correct me if I’m wrong), tester du ikke kun den tid det tager append() at indsætte et element; i dine tests konstruerer du også de elementer som skal indsættes med append()..:
//Simple test 1
appendTests["test01"] = function test01(insertIntoEle, numberOfElements) {
var ele = null;
for (var i = 0; i < numberOfElements; i++) {
jQuery("#insertIntoEle .insertIntoEle").append(createSimpleEle(i));
}
};
Som en side-note: html() vil altid vinde over append() i hastighed, da vi her snakker om kun et re-draw, og det at jQuery vil bruge innerHTML som er “native” for browseren, og derfor er meget hurtig.
Hej Thomas,
Ja, det er helt korrekt at jeg også opretter elementerne inden for den beregnede tid. Det er et helt bevidst valg fra min side eftersom jeg syntes det kunne bringe vigtig information ind i ligningen. Du vil jo altid, og nu må du jo rette mig, skulle oprette elementerne før du kan indsætte dem. Uden den opsætning ville vi jo heller ikke kunne sætte html indsættelsen op imod objektindsættelsen, eftersom vi så ville holde den del ude af problemstillingen. Men du har måske et andet syn på det?
Hvad angår html() imod append() er det sikkert helt korrekt. Append() benytter dog ikke html() til at indsætte, men den native javascript metode appendChild(). Så jeg syntes stadig resultatet er meget interessant.
Det man måske kan diskutere er hvor lækker html metoden er til at klare opgaven. Din kode vil blive mere uoverskuelig og svært tilgængelig hvis man opretter sine elementer med lange html tekststrenge .
Hvis din test skulle give et bedre overblik, kunne du oprette elementerne du indsætter først. Fx i et array objekt. På den måde er det kun append du tester, og derfor er dine resultater ikke forurenede af andre faktorer.
Mht. append() vs. html() er jeg selv pragmatisk (til en hvis grænse–hastighed vinder somregel i min Verden). Har jeg en stor mængde elementer som skal indsættes, giver html() mere mening end append(). Snakker vi om et enkelt eller to elementer; så er append() en ganske god løsning.
Din test forudsætter at man indsætter et stort antal elementer. Derfor synes jeg det giver god mening at du tilføjer en test-case hvor du bruger html(), som en slags “men man behøver ikke at skulle pakke append() ind i alt mulig logik for at øge hastighed”. Forstår du?
Ja, jeg tror jeg forstår. Der er dog en ting mere ved at inkludere selve oprettelsen af elementerne i testen. Det jo det samme for alle tests. Altså de skal alle sammen have genereret elementet og så sætte det ind. Så udgangspunktet er nøjagtigt det samme for alle tests. Derfor burde resultatet bestemt også være retvisende.
Jeg vil dog ikke helt afvise at der kan være en vis forskel, så måske jeg skulle udvide med en tredje og fjerde test, hvor jeg tager elementoprettelsen ud af ligningen. Det vil jeg lige se om jeg kan få stablet på benene i dag eller i morgen. Så laver jeg en opdatering på denne post.
/Rune
@Thomas
Så har jeg opdateret indlægget, og det er nu muligt at teste tidsforbruget UDEN elementoprettelse. Det er ikke meget man sparer på det, ser det ud til. Det tager altså ikke ret lang tid at oprette et element, i forhold til hvor lang tid det tager at indsætte det i DOM’en.
Håber det spreder lidt mere lys på problemstillingen.
/Rune