Skip to content

Commit f794d05

Browse files
committed
Improve packing performance
1 parent adad9ff commit f794d05

File tree

2 files changed

+70
-127
lines changed

2 files changed

+70
-127
lines changed

main.js

+68-125
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929

3030
// The dictionary
3131
var dictionary = {
32-
strings : [],
33-
integers : [],
34-
floats : []
32+
strings : {},
33+
integers : {},
34+
floats : {},
35+
stringsLen: 0,
36+
integersLen: 0,
37+
floatsLen: 0
3538
};
3639

3740
verbose && console.log('Creating the AST');
@@ -110,59 +113,70 @@
110113

111114
// Case 4: The item is String
112115
if (type === 'string') {
113-
116+
item = _encode(item);
114117
// The index of that word in the dictionary
115-
var index = _indexOf.call(dictionary.strings, item);
116-
117-
// If not, add to the dictionary and actualize the index
118-
if (index == -1) {
119-
dictionary.strings.push(_encode(item));
120-
index = dictionary.strings.length - 1;
118+
if (item in dictionary.strings) {
119+
// Return the token
120+
return {
121+
type : 'strings',
122+
index : dictionary.strings[item]
123+
}
124+
} else {
125+
// If not, add to the dictionary and actualize the index
126+
var index = dictionary.stringsLen;
127+
dictionary.strings[item] = index;
128+
dictionary.stringsLen += 1;
129+
// Return the token
130+
return {
131+
type : 'strings',
132+
index : index
133+
}
121134
}
122-
123-
// Return the token
124-
return {
125-
type : 'strings',
126-
index : index
127-
};
128135
}
129136

130137
// Case 5: The item is integer
131138
if (type === 'number' && item % 1 === 0) {
132-
139+
item = _base10To36(item);
133140
// The index of that number in the dictionary
134-
var index = _indexOf.call(dictionary.integers, item);
135-
136-
// If not, add to the dictionary and actualize the index
137-
if (index == -1) {
138-
dictionary.integers.push(_base10To36(item));
139-
index = dictionary.integers.length - 1;
141+
if(item in dictionary.integers) {
142+
// Return the token
143+
return {
144+
type : 'integers',
145+
index : dictionary.integers[item]
146+
};
147+
} else {
148+
// If not, add to the dictionary and actualize the index
149+
var index = dictionary.integersLen;
150+
dictionary.integers[item] = index;
151+
dictionary.integersLen += 1;
152+
// Return the token
153+
return {
154+
type : 'integers',
155+
index : index
156+
};
140157
}
141-
142-
// Return the token
143-
return {
144-
type : 'integers',
145-
index : index
146-
};
147158
}
148159

149160
// Case 6: The item is float
150161
if (type === 'number') {
151162
// The index of that number in the dictionary
152-
var index = _indexOf.call(dictionary.floats, item);
153-
154-
// If not, add to the dictionary and actualize the index
155-
if (index == -1) {
156-
// Float not use base 36
157-
dictionary.floats.push(item);
158-
index = dictionary.floats.length - 1;
163+
if(item in dictionary.floats) {
164+
// Return the token
165+
return {
166+
type : 'floats',
167+
index : dictionary.floats[item]
168+
};
169+
} else {
170+
// If not, add to the dictionary and actualize the index
171+
var index = dictionary.floatsLen;
172+
dictionary.floats[item] = index;
173+
dictionary.floatsLen += 1;
174+
// Return the token
175+
return {
176+
type : 'floats',
177+
index : index
178+
};
159179
}
160-
161-
// Return the token
162-
return {
163-
type : 'floats',
164-
index : index
165-
};
166180
}
167181

168182
// Case 7: The item is boolean
@@ -179,16 +193,16 @@
179193
})(json);
180194

181195
// A set of shorthands proxies for the length of the dictionaries
182-
var stringLength = dictionary.strings.length;
183-
var integerLength = dictionary.integers.length;
184-
var floatLength = dictionary.floats.length;
196+
var stringLength = dictionary.stringsLen;
197+
var integerLength = dictionary.integersLen;
198+
var floatLength = dictionary.floatsLen;
185199

186200
verbose && console.log('Parsing the dictionary');
187201

188202
// Create a raw dictionary
189-
var packed = dictionary.strings.join('|');
190-
packed += '^' + dictionary.integers.join('|');
191-
packed += '^' + dictionary.floats.join('|');
203+
var packed = _getSortedKeys(dictionary.strings, dictionary.stringsLen).join('|');
204+
packed += '^' + _getSortedKeys(dictionary.integers, dictionary.integersLen).join('|');
205+
packed += '^' + _getSortedKeys(dictionary.floats, dictionary.floatsLen).join('|');
192206

193207
verbose && console.log('Parsing the structure');
194208

@@ -442,75 +456,14 @@
442456
})();
443457

444458
}
445-
/**
446-
* Get the index value of the dictionary
447-
* @param {Object} dictionary a object that have two array attributes: 'string' and 'number'
448-
* @param {Object} data
449-
*/
450-
var _indexOfDictionary = function(dictionary, value) {
451-
452-
// The type of the value
453-
var type = typeof value;
454-
455-
// If is boolean, return a boolean token
456-
if (type === 'boolean')
457-
return value ? TOKEN_TRUE : TOKEN_FALSE;
458-
459-
// If is null, return a... yes! the null token
460-
if (value === null)
461-
return TOKEN_NULL;
462-
463-
//add undefined
464-
if (typeof value === 'undefined')
465-
return TOKEN_UNDEFINED;
466-
467459

468-
if (value === '') {
469-
return TOKEN_EMPTY_STRING;
460+
var _getSortedKeys = function(dict, len) {
461+
var arr = new Array(len);
462+
for (var key in dict) {
463+
arr[dict[key]] = key;
470464
}
471-
472-
if (type === 'string') {
473-
value = _encode(value);
474-
var index = _indexOf.call(dictionary.strings, value);
475-
if (index === -1) {
476-
dictionary.strings.push(value);
477-
index = dictionary.strings.length - 1;
478-
}
479-
}
480-
481-
// If has an invalid JSON type (example a function)
482-
if (type !== 'string' && type !== 'number') {
483-
throw new Error('The type is not a JSON type');
484-
};
485-
486-
if (type === 'string') {// string
487-
value = _encode(value);
488-
} else if (value % 1 === 0) {// integer
489-
value = _base10To36(value);
490-
} else {// float
491-
492-
}
493-
494-
// If is number, "serialize" the value
495-
value = type === 'number' ? _base10To36(value) : _encode(value);
496-
497-
// Retrieve the index of that value in the dictionary
498-
var index = _indexOf.call(dictionary[type], value);
499-
500-
// If that value is not in the dictionary
501-
if (index === -1) {
502-
// Push the value
503-
dictionary[type].push(value);
504-
// And return their index
505-
index = dictionary[type].length - 1;
506-
}
507-
508-
// If the type is a number, then add the '+' prefix character
509-
// to differentiate that they is a number index. If not, then
510-
// just return a 36-based representation of the index
511-
return type === 'number' ? '+' + index : index;
512-
513-
};
465+
return arr;
466+
}
514467

515468
var _encode = function(str) {
516469
if ( typeof str !== 'string')
@@ -550,16 +503,6 @@
550503
return parseInt(number, 36);
551504
};
552505

553-
var _indexOf = Array.prototype.indexOf ||
554-
function(obj, start) {
555-
for (var i = (start || 0), j = this.length; i < j; i++) {
556-
if (this[i] === obj) {
557-
return i;
558-
}
559-
}
560-
return -1;
561-
};
562-
563506
return {
564507
JSON : JSON,
565508
pack : pack,

test/test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ describe('jsonpack', function() {
2525
attr2 : plainObject,
2626
attr3 : [plainObject, plainObject]
2727
},
28-
deepObjectPacked = "attr1|string|hello|integer|float|true|false|null|attr2|attr3^1J9|1J9|1J9|1J9^1.2^$0|$1|2|3|A|4|E|5|-1|6|-2|7|-3]|8|$1|2|3|B|4|E|5|-1|6|-2|7|-3]|9|@$1|2|3|C|4|E|5|-1|6|-2|7|-3]|$1|2|3|D|4|E|5|-1|6|-2|7|-3]]]";
28+
deepObjectPacked = "attr1|string|hello|integer|float|true|false|null|attr2|attr3^1J9^1.2^$0|$1|2|3|A|4|B|5|-1|6|-2|7|-3]|8|$1|2|3|A|4|B|5|-1|6|-2|7|-3]|9|@$1|2|3|A|4|B|5|-1|6|-2|7|-3]|$1|2|3|A|4|B|5|-1|6|-2|7|-3]]]";
2929

3030
var arrayObject = [
3131
plainObject,
3232
deepObject
3333
],
34-
arrayObjectPacked = "string|hello|integer|float|true|false|null|attr1|attr2|attr3^1J9|1J9|1J9|1J9|1J9^1.2^@$0|1|2|A|3|F|4|-1|5|-2|6|-3]|$7|$0|1|2|B|3|F|4|-1|5|-2|6|-3]|8|$0|1|2|C|3|F|4|-1|5|-2|6|-3]|9|@$0|1|2|D|3|F|4|-1|5|-2|6|-3]|$0|1|2|E|3|F|4|-1|5|-2|6|-3]]]]";
34+
arrayObjectPacked = "string|hello|integer|float|true|false|null|attr1|attr2|attr3^1J9^1.2^@$0|1|2|A|3|B|4|-1|5|-2|6|-3]|$7|$0|1|2|A|3|B|4|-1|5|-2|6|-3]|8|$0|1|2|A|3|B|4|-1|5|-2|6|-3]|9|@$0|1|2|A|3|B|4|-1|5|-2|6|-3]|$0|1|2|A|3|B|4|-1|5|-2|6|-3]]]]";
3535

3636
describe('elemental', function() {
3737

0 commit comments

Comments
 (0)