- Die Frage ist schon etwas älter, aber ich wollte diese Antwort schreiben, um Ihnen einige Benchmarks zu zeigen, die ich auf der Grundlage aller hier gegebenen Antworten und des von Jim Buck veröffentlichten jsperf erstellt habe.
Ich brauchte eine schnelle Methode, um herauszufinden, ob sich eine lange Nadel in einem langen Heuhaufen befindet, und sie sind sich bis auf die letzten Zeichen sehr ähnlich.
Hier ist der Code, den ich geschrieben habe und der für jede Funktion (splice, substring, startsWith, etc.) testet, ob sie false oder true zurückgibt, anhand einer Heuhaufen-Zeichenkette ( nestedString
) von 1.000.0001 Zeichen und eine falsche oder wahre Nadelfolge von 1.000.000 Zeichen ( testParentStringFalse
y testParentStringTrue
bzw.):
// nestedString is made of 1.000.001 '1' repeated characters.
var nestedString = '...'
// testParentStringFalse is made of 1.000.000 characters,
// all characters are repeated '1', but the last one is '2',
// so for this string the test should return false.
var testParentStringFalse = '...'
// testParentStringTrue is made of 1.000.000 '1' repeated characters,
// so for this string the test should return true.
var testParentStringTrue = '...'
// You can make these very long strings by running the following bash command
// and edit each one as needed in your editor
// (NOTE: on OS X, `pbcopy` copies the string to the clipboard buffer,
// on Linux, you would probably need to replace it with `xclip`):
//
// printf '1%.0s' {1..1000000} | pbcopy
//
function testString() {
let dateStart
let dateEnd
let avg
let count = 100000
const falseResults = []
const trueResults = []
/* slice */
console.log('========> slice')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.slice(0, testParentStringFalse.length) === testParentStringFalse
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
falseResults[falseResults.length] = {
label: 'slice',
avg
}
console.log(`testString() slice = false`, res, 'avg: ' + avg + 'ms')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.slice(0, testParentStringTrue.length) === testParentStringTrue
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
trueResults[trueResults.length] = {
label: 'slice',
avg
}
console.log(`testString() slice = true`, res, 'avg: ' + avg + 'ms')
console.log('<======== slice')
console.log('')
/* slice END */
/* lastIndexOf */
console.log('========> lastIndexOf')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.lastIndexOf(testParentStringFalse, 0) === 0
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
falseResults[falseResults.length] = {
label: 'lastIndexOf',
avg
}
console.log(`testString() lastIndexOf = false`, res, 'avg: ' + avg + 'ms')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.lastIndexOf(testParentStringTrue, 0) === 0
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
trueResults[trueResults.length] = {
label: 'lastIndexOf',
avg
}
console.log(`testString() lastIndexOf = true`, res, 'avg: ' + avg + 'ms')
console.log('<======== lastIndexOf')
console.log('')
/* lastIndexOf END */
/* indexOf */
console.log('========> indexOf')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.indexOf(testParentStringFalse) === 0
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
falseResults[falseResults.length] = {
label: 'indexOf',
avg
}
console.log(`testString() indexOf = false`, res, 'avg: ' + avg + 'ms')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.indexOf(testParentStringTrue) === 0
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
trueResults[trueResults.length] = {
label: 'indexOf',
avg
}
console.log(`testString() indexOf = true`, res, 'avg: ' + avg + 'ms')
console.log('<======== indexOf')
console.log('')
/* indexOf END */
/* substring */
console.log('========> substring')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.substring(0, testParentStringFalse.length) === testParentStringFalse
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
falseResults[falseResults.length] = {
label: 'substring',
avg
}
console.log(`testString() substring = false`, res, 'avg: ' + avg + 'ms')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.substring(0, testParentStringTrue.length) === testParentStringTrue
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
trueResults[trueResults.length] = {
label: 'substring',
avg
}
console.log(`testString() substring = true`, res, 'avg: ' + avg + 'ms')
console.log('<======== substring')
console.log('')
/* substring END */
/* startsWith */
console.log('========> startsWith')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.startsWith(testParentStringFalse)
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
falseResults[falseResults.length] = {
label: 'startsWith',
avg
}
console.log(`testString() startsWith = false`, res, 'avg: ' + avg + 'ms')
dateStart = +new Date()
var res
for (let j = 0; j < count; j++) {
res = nestedString.startsWith(testParentStringTrue)
}
dateEnd = +new Date()
avg = (dateEnd - dateStart)/count
trueResults[trueResults.length] = {
label: 'startsWith',
avg
}
console.log(`testString() startsWith = true`, res, 'avg: ' + avg + 'ms')
console.log('<======== startsWith')
console.log('')
/* startsWith END */
falseResults.sort((a, b) => a.avg - b.avg)
trueResults.sort((a, b) => a.avg - b.avg)
console.log('false results from fastest to slowest avg:', falseResults)
console.log('true results from fastest to slowest avg:', trueResults)
}
Ich habe diesen Benchmark-Test unter folgenden Bedingungen durchgeführt Chrom 75 , Firefox 67 , Safari 12 y Oper 62 .
Ich habe Edge und IE nicht einbezogen, weil ich sie nicht auf diesem Rechner habe, aber wenn jemand von euch das Skript gegen Edge und zumindest IE 9 ausführen und die Ausgabe hier teilen möchte, wäre ich sehr neugierig auf die Ergebnisse.
Denken Sie nur daran, dass Sie die 3 langen Strings neu erstellen und das Skript in einer Datei speichern müssen, die Sie dann in Ihrem Browser öffnen, da die Konsole des Browsers beim Kopieren/Einfügen blockiert wird, da die Länge jedes Strings >= 1.000.000 ist).
Hier sind die Ergebnisse:
Chrom 75 ( substring
gewinnt):
false results from fastest to slowest avg:
1) {"label":"substring","avg":0.08271}
2) {"label":"slice","avg":0.08615}
3) {"label":"lastIndexOf","avg":0.77025}
4) {"label":"indexOf","avg":1.64375}
5) {"label":"startsWith","avg":3.5454}
true results from fastest to slowest avg:
1) {"label":"substring","avg":0.08213}
2) {"label":"slice","avg":0.08342}
3) {"label":"lastIndexOf","avg":0.7831}
4) {"label":"indexOf","avg":0.88988}
5) {"label":"startsWith","avg":3.55448}
Firefox 67 ( indexOf
gewinnt):
false results from fastest to slowest avg
1) {"label":"indexOf","avg":0.1807}
2) {"label":"startsWith","avg":0.74621}
3) {"label":"substring","avg":0.74898}
4) {"label":"slice","avg":0.78584}
5) {"label":"lastIndexOf","avg":0.79668}
true results from fastest to slowest avg:
1) {"label":"indexOf","avg":0.09528}
2) {"label":"substring","avg":0.75468}
3) {"label":"startsWith","avg":0.76717}
4) {"label":"slice","avg":0.77222}
5) {"label":"lastIndexOf","avg":0.80527}
Safari 12 ( slice
gewinnt für falsche Ergebnisse, startsWith
gewinnt für echte Ergebnisse, außerdem ist Safari der schnellste in Bezug auf die Gesamtzeit für die Ausführung des gesamten Tests):
false results from fastest to slowest avg:
1) "{\"label\":\"slice\",\"avg\":0.0362}"
2) "{\"label\":\"startsWith\",\"avg\":0.1141}"
3) "{\"label\":\"lastIndexOf\",\"avg\":0.11512}"
4) "{\"label\":\"substring\",\"avg\":0.14751}"
5) "{\"label\":\"indexOf\",\"avg\":0.23109}"
true results from fastest to slowest avg:
1) "{\"label\":\"startsWith\",\"avg\":0.11207}"
2) "{\"label\":\"lastIndexOf\",\"avg\":0.12196}"
3) "{\"label\":\"substring\",\"avg\":0.12495}"
4) "{\"label\":\"indexOf\",\"avg\":0.33667}"
5) "{\"label\":\"slice\",\"avg\":0.49923}"
Oper 62 ( substring
gewinnt. Die Ergebnisse sind ähnlich wie bei Chrome und das überrascht mich nicht, da Opera auf Chromium und Blink basiert):
false results from fastest to slowest avg:
{"label":"substring","avg":0.09321}
{"label":"slice","avg":0.09463}
{"label":"lastIndexOf","avg":0.95347}
{"label":"indexOf","avg":1.6337}
{"label":"startsWith","avg":3.61454}
true results from fastest to slowest avg:
1) {"label":"substring","avg":0.08855}
2) {"label":"slice","avg":0.12227}
3) {"label":"indexOf","avg":0.79914}
4) {"label":"lastIndexOf","avg":1.05086}
5) {"label":"startsWith","avg":3.70808}
Es stellt sich heraus, dass jeder Browser seine eigenen Implementierungsdetails hat (mit Ausnahme von Opera, das auf Chromium und Blink von Chrome basiert).
Natürlich könnten und sollten weitere Tests mit verschiedenen Anwendungsfällen durchgeführt werden (z.B. wenn die Nadel im Vergleich zum Heuhaufen wirklich kurz ist, wenn der Heuhaufen kürzer als die Nadel ist, usw.), aber in meinem Fall musste ich sehr lange Strings vergleichen und wollte dies hier mitteilen.