|
|
|
@ -1,21 +1,12 @@
|
|
|
|
|
<!doctype html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8"/>
|
|
|
|
|
<title>Compression test</title>
|
|
|
|
|
<script src="LZMA-JS/src/lzma_worker.js"></script>
|
|
|
|
|
<script src="node-lz4/build/lz4.js"></script>
|
|
|
|
|
<script src="lz-string/libs/lz-string.js"></script>
|
|
|
|
|
<script >
|
|
|
|
|
function _log(str, tag) {
|
|
|
|
|
const logEntry = document.createElement(tag);
|
|
|
|
|
logEntry.innerText = str;
|
|
|
|
|
logEntry.classList.add('log-entry');
|
|
|
|
|
document.getElementById("log").appendChild(logEntry);
|
|
|
|
|
}
|
|
|
|
|
function log(str) {
|
|
|
|
|
_log(str, 'span');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var Buffer = require('buffer').Buffer
|
|
|
|
|
var LZ4 = require('lz4')
|
|
|
|
|
|
|
|
|
@ -108,38 +99,97 @@
|
|
|
|
|
|
|
|
|
|
const compressors = {lzma: LZMAPre, lz4: LZ4Pre, lzString: LZStringPre};
|
|
|
|
|
|
|
|
|
|
const resultTable = document.getElementById('results');
|
|
|
|
|
const headerRow = resultTable.querySelector('thead tr');
|
|
|
|
|
const prefixRow = document.getElementById('prefix-row');
|
|
|
|
|
const tbody = resultTable.querySelector('tbody');
|
|
|
|
|
|
|
|
|
|
const prefixSize = document.createElement('td');
|
|
|
|
|
prefixSize.innerText = prefix.length;
|
|
|
|
|
prefixRow.appendChild(prefixSize);
|
|
|
|
|
|
|
|
|
|
function appendHeader(str) {
|
|
|
|
|
const th = document.createElement('th');
|
|
|
|
|
th.innerText = str;
|
|
|
|
|
headerRow.appendChild(th);
|
|
|
|
|
}
|
|
|
|
|
function appendPrefixCell(str) {
|
|
|
|
|
const td = document.createElement('td');
|
|
|
|
|
if (str) td.innerText = str;
|
|
|
|
|
prefixRow.appendChild(td);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const name in compressors) {
|
|
|
|
|
const algo = compressors[name];
|
|
|
|
|
_log("-------- Testing algorithm: " + name + " --------", 'h1')
|
|
|
|
|
appendHeader(name);
|
|
|
|
|
appendHeader('?');
|
|
|
|
|
appendHeader(name + " w/ prefix");
|
|
|
|
|
appendHeader('?');
|
|
|
|
|
appendHeader(name + " incl. prefix");
|
|
|
|
|
appendHeader("matched");
|
|
|
|
|
appendHeader("skipped");
|
|
|
|
|
appendHeader("remaining");
|
|
|
|
|
|
|
|
|
|
const prefix_compressed = algo.baseCompress(prefix);
|
|
|
|
|
const prefix_compressed_len = prefix_compressed.length;
|
|
|
|
|
log("prefix (" + prefix.length + " bytes) compressed to "
|
|
|
|
|
+ prefix_compressed_len + " bytes.");
|
|
|
|
|
appendPrefixCell(prefix_compressed_len);
|
|
|
|
|
for (var i = 0; i < 7; i++) appendPrefixCell();
|
|
|
|
|
|
|
|
|
|
for (const filename in exampleFiles) {
|
|
|
|
|
const str = exampleFiles[filename];
|
|
|
|
|
|
|
|
|
|
const rowId = 'row-' + filename;
|
|
|
|
|
var row = document.getElementById(rowId);
|
|
|
|
|
if (!row) {
|
|
|
|
|
row = document.createElement('tr');
|
|
|
|
|
row.id = rowId;
|
|
|
|
|
|
|
|
|
|
const rowHeader = document.createElement('th');
|
|
|
|
|
rowHeader.innerText = filename;
|
|
|
|
|
row.appendChild(rowHeader);
|
|
|
|
|
|
|
|
|
|
const size = document.createElement('td');
|
|
|
|
|
size.innerText = str.length;
|
|
|
|
|
row.appendChild(size);
|
|
|
|
|
|
|
|
|
|
tbody.appendChild(row);
|
|
|
|
|
}
|
|
|
|
|
function appendCell(str) {
|
|
|
|
|
const td = document.createElement('td');
|
|
|
|
|
if (str === undefined) str = '';
|
|
|
|
|
else if (str === true) str = '✔️';
|
|
|
|
|
else if (str === false) str = '❌';
|
|
|
|
|
td.innerText = str;
|
|
|
|
|
row.appendChild(td);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = algo.baseCompress(str);
|
|
|
|
|
log(filename + " (" + str.length + " bytes) compressed to " + result.length + " bytes. Decompression succesful? " + (str == algo.baseDecompress(result)));
|
|
|
|
|
appendCell(result.length);
|
|
|
|
|
appendCell(str == algo.baseDecompress(result))
|
|
|
|
|
var bestLength = result.length;
|
|
|
|
|
result = algo.compress(str);
|
|
|
|
|
const decompressionSuccessful = (str == algo.decompress(result));
|
|
|
|
|
log(filename + " compressed using prefix to " + result.length + " bytes. Decompression succesful? " + decompressionSuccessful);
|
|
|
|
|
appendCell(result.length);
|
|
|
|
|
appendCell(decompressionSuccessful)
|
|
|
|
|
|
|
|
|
|
if (!decompressionSuccessful) {
|
|
|
|
|
var bestDescription = "Prefix compression failed.";
|
|
|
|
|
var bestCells = ['', '', ''];
|
|
|
|
|
result = algo.baseCompress(prefix + str)
|
|
|
|
|
log(filename + " compressed with prefix to " + result.length + " bytes, an extra " + (result.length - prefix_compressed_len) + " bytes.");
|
|
|
|
|
appendCell(result.length);
|
|
|
|
|
for (var j = 0; j < prefix_compressed_len; j++) {
|
|
|
|
|
for (var i = j; i < prefix_compressed_len && prefix_compressed[i] == result[i]; i++) { }
|
|
|
|
|
const truncatedLength = result.length - i + j;
|
|
|
|
|
if (truncatedLength < bestLength) {
|
|
|
|
|
bestLength = truncatedLength;
|
|
|
|
|
bestDescription = filename + " compressed with prefix matches " + (i-j) + " bytes (skipping " + j + " bytes) of compressed prefix. Remaining length is " + truncatedLength + " bytes"
|
|
|
|
|
bestCells = [i-j, j, truncatedLength]
|
|
|
|
|
}
|
|
|
|
|
j = i;
|
|
|
|
|
}
|
|
|
|
|
log(bestDescription);
|
|
|
|
|
for (const cell of bestCells) appendCell(cell);
|
|
|
|
|
} else {
|
|
|
|
|
for (var i = 0; i < 4; i++) appendCell();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -147,21 +197,39 @@
|
|
|
|
|
testCompression();
|
|
|
|
|
</script>
|
|
|
|
|
<style>
|
|
|
|
|
#log {
|
|
|
|
|
display: table;
|
|
|
|
|
td {
|
|
|
|
|
text-align: right;
|
|
|
|
|
}
|
|
|
|
|
table {
|
|
|
|
|
border-spacing: 0;
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
}
|
|
|
|
|
table, tr, th, td {
|
|
|
|
|
border: 1px solid #DDD;
|
|
|
|
|
}
|
|
|
|
|
#log .log-entry {
|
|
|
|
|
display: block;
|
|
|
|
|
background: lightblue;
|
|
|
|
|
border: solid black 2px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
tr:nth-child(2n) {
|
|
|
|
|
background-color: #f6f8fa;
|
|
|
|
|
}
|
|
|
|
|
#log .log-entry:nth-child(odd) {
|
|
|
|
|
background: lightyellow;
|
|
|
|
|
thead th {
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
background: white;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div id="log"></div>
|
|
|
|
|
<table id="results">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Filename</th>
|
|
|
|
|
<th>Size</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr id="prefix-row">
|
|
|
|
|
<th>PREFIX</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|