Word frequency counting strategies
JavaScript performance comparison
Preparation code
<section id="word-report">
<h3>Word frequency report</h3>
<p>
The most frequent words found by the last counting run.
</p>
<table id="report-table">
<thead>
<tr>
<th>Rank</th>
<th>Word</th>
<th>Occurrences</th>
</tr>
</thead>
<tbody id="report-body">
</tbody>
</table>
<ul id="report-notes">
<li>Words are lower-cased before they are counted.</li>
<li>Anything that is not a letter separates two words.</li>
<li>Words with the same count are ordered alphabetically.</li>
</ul>
<p id="report-status">No run recorded yet.</p>
</section>
<script>
Benchmark.prototype.setup = function() {
var sentences = [
'The quick brown fox jumps over the lazy dog while the sun sets.',
'A watched pot never boils, but the kettle on the stove always does.',
'The library opens at nine and the reading room is quiet until noon.',
'Every morning the baker shapes the dough and the town smells of bread.',
'The river bends around the old mill and the water runs clear and cold.',
'A good question is worth more than a quick answer, said the teacher.',
'The train to the coast leaves at dawn and returns after the lights are on.',
'In the garden the beans climb the poles and the tomatoes turn red.',
'The painter mixed the blue with a little white and the sky appeared.',
'When the bell rings the children run to the yard and the game begins.',
'The map showed a path through the hills, past the lake and over the bridge.',
'The clock in the tower is slow, so the town is always a minute late.'
];
var corpus = [];
for (var round = 0; round < 40; round++) {
for (var s = 0; s < sentences.length; s++) {
corpus.push(sentences[s]);
}
}
var text = corpus.join(' ');
var TOP = 5;
function tokenize(source) {
return source.toLowerCase().split(/[^a-z]+/).filter(function (word) {
return word.length > 0;
});
}
function byCountThenWord(a, b) {
return (b.count - a.count) || (a.word < b.word ? -1 : (a.word > b.word ? 1 : 0));
}
var words = tokenize(text);
function expectedTop() {
var seen = {};
var list = [];
words.forEach(function (word) {
if (seen[word] === undefined) {
seen[word] = list.length;
list.push({ word: word, count: 0 });
}
list[seen[word]].count++;
});
return list.sort(byCountThenWord).slice(0, TOP);
}
var expected = expectedTop();
var result = null;
};
Benchmark.prototype.teardown = function() {
function sameRanking(actual, wanted) {
if (!actual || actual.length !== wanted.length) {
return false;
}
for (var i = 0; i < wanted.length; i++) {
if (actual[i].word !== wanted[i].word || actual[i].count !== wanted[i].count) {
return false;
}
}
return true;
}
var correct = sameRanking(result, expected);
var reportBody = document.getElementById("report-body");
var reportStatus = document.getElementById("report-status");
if (reportBody && result) {
var rows = "";
for (var rank = 0; rank < result.length; rank++) {
rows += "<tr><td>" + (rank + 1) + "</td><td>" + result[rank].word + "</td><td>" + result[rank].count + "</td></tr>";
}
reportBody.innerHTML = rows;
}
if (reportStatus) {
reportStatus.textContent = correct ? "The last run matched the expected ranking." : "The last run did not match the expected ranking.";
}
if (!correct) {
throw new Error("Word frequency result differs from the expected ranking");
}
result = null;
};
</script>
Preparation code output
<section id="word-report">
<h3>Word frequency report</h3>
<p>
The most frequent words found by the last counting run.
</p>
<table id="report-table">
<thead>
<tr>
<th>Rank</th>
<th>Word</th>
<th>Occurrences</th>
</tr>
</thead>
<tbody id="report-body">
</tbody>
</table>
<ul id="report-notes">
<li>Words are lower-cased before they are counted.</li>
<li>Anything that is not a letter separates two words.</li>
<li>Words with the same count are ordered alphabetically.</li>
</ul>
<p id="report-status">No run recorded yet.</p>
</section>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
|
Map counter
|
|
pending… |
|
Object counter
|
|
pending… |
|
Sort and run-length
|
|
pending… |
Revisions
You can edit these tests or add even more tests to this page by appending /edit to the URL.
- Revision 1: published testuser
- Revision 2: published Test User
0 Comments