Skip to content

Commit d49be80

Browse files
committed
Allocate Nodes in sets of 50,000 at a time. MUCH faster.
Rather than calling `Newz()` to allocate Nodes one at a time as we need them, allocate them sets of 50,000 at a time; a NodeSet. Nodes themselves are still managed as a doubly linked list, this commit just changes how we allocate them to boost performance.
1 parent e5e1f30 commit d49be80

2 files changed

Lines changed: 45 additions & 20 deletions

File tree

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Revision history for Perl extension JavaScript::Minifier::XS.
22

33
{{$NEXT}}
44
- rewrote test suite into a single ".t" test
5+
- optimized memory allocations, by allocating Nodes in bulk
56

67
0.13 2020-12-30 21:46:29-08:00 America/Vancouver
78
- POD cleanups; spelling, SYNOPSIS

XS.xs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,22 @@ struct _Node {
107107
NodeType type;
108108
};
109109

110+
#define NODE_SET_SIZE 50000
111+
112+
struct _NodeSet;
113+
typedef struct _NodeSet NodeSet;
114+
struct _NodeSet {
115+
/* link to next NodeSet */
116+
NodeSet* next;
117+
/* Nodes in this Set */
118+
Node nodes[NODE_SET_SIZE];
119+
size_t next_node;
120+
};
121+
110122
typedef struct {
123+
/* singly linked list of NodeSets */
124+
NodeSet* head_set;
125+
NodeSet* tail_set;
111126
/* linked list pointers */
112127
Node* head;
113128
Node* tail;
@@ -196,9 +211,24 @@ bool nodeEndsWith(Node* node, const char* string) {
196211
* ****************************************************************************
197212
*/
198213
/* allocates a new node */
199-
Node* JsAllocNode() {
214+
Node* JsAllocNode(JsDoc* doc) {
200215
Node* node;
201-
Newz(0, node, 1, Node);
216+
NodeSet* set = doc->tail_set;
217+
218+
/* if our current NodeSet is full, allocate a new NodeSet */
219+
if (set->next_node >= NODE_SET_SIZE) {
220+
NodeSet* next_set;
221+
Newz(0, next_set, 1, NodeSet);
222+
set->next = next_set;
223+
doc->tail_set = next_set;
224+
set = next_set;
225+
}
226+
227+
/* grab the next Node out of the NodeSet */
228+
node = set->nodes + set->next_node;
229+
set->next_node ++;
230+
231+
/* initialize the node */
202232
node->prev = NULL;
203233
node->next = NULL;
204234
node->contents = NULL;
@@ -207,20 +237,6 @@ Node* JsAllocNode() {
207237
return node;
208238
}
209239

210-
/* frees the memory used by a node */
211-
void JsFreeNode(Node* node) {
212-
if (node->contents)
213-
Safefree(node->contents);
214-
Safefree(node);
215-
}
216-
void JsFreeNodeList(Node* head) {
217-
while (head) {
218-
Node* tmp = head->next;
219-
JsFreeNode(head);
220-
head = tmp;
221-
}
222-
}
223-
224240
/* clears the contents of a node */
225241
void JsClearNodeContents(Node* node) {
226242
if (node->contents)
@@ -246,7 +262,6 @@ void JsDiscardNode(Node* node) {
246262
node->prev->next = node->next;
247263
if (node->next)
248264
node->next->prev = node->prev;
249-
JsFreeNode(node);
250265
}
251266

252267
/* appends the node to the given element */
@@ -406,7 +421,7 @@ Node* JsTokenizeString(JsDoc* doc, const char* string) {
406421
/* parse the JS */
407422
while ((doc->offset < doc->length) && (doc->buffer[doc->offset])) {
408423
/* allocate a new node */
409-
Node* node = JsAllocNode();
424+
Node* node = JsAllocNode(doc);
410425
if (!doc->head)
411426
doc->head = node;
412427
if (!doc->tail)
@@ -686,6 +701,8 @@ char* JsMinify(const char* string) {
686701
doc.buffer = string;
687702
doc.length = strlen(string);
688703
doc.offset = 0;
704+
Newz(0, doc.head_set, 1, NodeSet);
705+
doc.tail_set = doc.head_set;
689706

690707
/* PASS 1: tokenize JS into a list of nodes */
691708
Node* head = JsTokenizeString(&doc, string);
@@ -713,8 +730,15 @@ char* JsMinify(const char* string) {
713730
}
714731
*ptr = 0;
715732
}
716-
/* free memory used by node list */
717-
JsFreeNodeList(head);
733+
/* free memory used by the NodeSets */
734+
{
735+
NodeSet* curr = doc.head_set;
736+
while (curr) {
737+
NodeSet* next = curr->next;
738+
Safefree(curr);
739+
curr = next;
740+
}
741+
}
718742
/* return resulting minified JS back to caller */
719743
return results;
720744
}

0 commit comments

Comments
 (0)