Mercurial > pidgin
comparison src/xmlnode.c @ 12233:02833a0ae716
[gaim-migrate @ 14535]
SF Patch #1367116 from Michael Carlson
"In profiling gaim, I noticed that on simply starting
CVS gaim, xmlnode_insert_child is using up by far the
most CPU time. After some testing, I realized the
reason why: xmlnode_insert_child is called some 18,000
times on startup, and it is inserting the child at the
end of the list each time, simply by traversing through
the entire linked list. Sometimes this list can have as
many as 800 elements.
This patch adds a variable to the _xmlnode struct,
lastchild, which simply keeps track of the last node in
the list of children. This is then used by
xmlnode_insert_child to insert at the end of the list,
instead of traversing through the whole list each time.
The two relevant functions in xmlnode.c that need to be
updated to keep track of this function appropriately
have been updated.
Running 3 times with and without the change, the
results from oprofile say it all. Here are the measured
number of clock cycles / % of total clock cycles /
function used to simply start and close gaim before the
change:
204 60.7143 xmlnode_insert_child
210 61.4035 xmlnode_insert_child
230 61.8280 xmlnode_insert_child
And after (note that one time no clock cycles were
caught at all)
3 2.5862 xmlnode_insert_child
3 2.5641 xmlnode_insert_child
This affects other areas of the program than just
starting up, but this seems to be the most noticeable
place."
Speed is good. As I was verifying this patch, I added some g_return_val_if_fail() checks.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 27 Nov 2005 03:42:39 +0000 |
parents | 9679b615edb8 |
children | 25e63008d3bb |
comparison
equal
deleted
inserted
replaced
12232:375f1f3817a8 | 12233:02833a0ae716 |
---|---|
81 g_return_if_fail(parent != NULL); | 81 g_return_if_fail(parent != NULL); |
82 g_return_if_fail(child != NULL); | 82 g_return_if_fail(child != NULL); |
83 | 83 |
84 child->parent = parent; | 84 child->parent = parent; |
85 | 85 |
86 if(parent->child) { | 86 if(parent->lastchild) { |
87 xmlnode *x; | 87 parent->lastchild->next = child; |
88 for(x = parent->child; x->next; x = x->next); | |
89 x->next = child; | |
90 } else { | 88 } else { |
91 parent->child = child; | 89 parent->child = child; |
92 } | 90 } |
91 | |
92 parent->lastchild = child; | |
93 } | 93 } |
94 | 94 |
95 void | 95 void |
96 xmlnode_insert_data(xmlnode *node, const char *data, gssize size) | 96 xmlnode_insert_data(xmlnode *node, const char *data, gssize size) |
97 { | 97 { |
124 { | 124 { |
125 if(attr_node->type == XMLNODE_TYPE_ATTRIB && | 125 if(attr_node->type == XMLNODE_TYPE_ATTRIB && |
126 !strcmp(attr_node->name, attr)) { | 126 !strcmp(attr_node->name, attr)) { |
127 if(node->child == attr_node) { | 127 if(node->child == attr_node) { |
128 node->child = attr_node->next; | 128 node->child = attr_node->next; |
129 } else if (node->lastchild == attr_node) { | |
130 node->lastchild = sibling; | |
129 } else { | 131 } else { |
130 sibling->next = attr_node->next; | 132 sibling->next = attr_node->next; |
131 } | 133 } |
132 xmlnode_free(attr_node); | 134 xmlnode_free(attr_node); |
133 return; | 135 return; |
203 xmlnode *x, *ret = NULL; | 205 xmlnode *x, *ret = NULL; |
204 char **names; | 206 char **names; |
205 char *parent_name, *child_name; | 207 char *parent_name, *child_name; |
206 | 208 |
207 g_return_val_if_fail(parent != NULL, NULL); | 209 g_return_val_if_fail(parent != NULL, NULL); |
210 g_return_val_if_fail(name != NULL, NULL); | |
208 | 211 |
209 names = g_strsplit(name, "/", 2); | 212 names = g_strsplit(name, "/", 2); |
210 parent_name = names[0]; | 213 parent_name = names[0]; |
211 child_name = names[1]; | 214 child_name = names[1]; |
212 | 215 |
256 { | 259 { |
257 GString *text = g_string_new(""); | 260 GString *text = g_string_new(""); |
258 xmlnode *c; | 261 xmlnode *c; |
259 char *node_name, *esc, *esc2, *tab = NULL; | 262 char *node_name, *esc, *esc2, *tab = NULL; |
260 gboolean need_end = FALSE, pretty = formatting; | 263 gboolean need_end = FALSE, pretty = formatting; |
264 | |
265 g_return_val_if_fail(node != NULL, NULL); | |
261 | 266 |
262 if(pretty && depth) { | 267 if(pretty && depth) { |
263 tab = g_strnfill(depth, '\t'); | 268 tab = g_strnfill(depth, '\t'); |
264 text = g_string_append(text, tab); | 269 text = g_string_append(text, tab); |
265 } | 270 } |
326 char * | 331 char * |
327 xmlnode_to_formatted_str(xmlnode *node, int *len) | 332 xmlnode_to_formatted_str(xmlnode *node, int *len) |
328 { | 333 { |
329 char *xml, *xml_with_declaration; | 334 char *xml, *xml_with_declaration; |
330 | 335 |
336 g_return_val_if_fail(node != NULL, NULL); | |
337 | |
331 xml = xmlnode_to_str_helper(node, len, TRUE, 0); | 338 xml = xmlnode_to_str_helper(node, len, TRUE, 0); |
332 xml_with_declaration = | 339 xml_with_declaration = |
333 g_strdup_printf("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S "%s", xml); | 340 g_strdup_printf("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S "%s", xml); |
334 g_free(xml); | 341 g_free(xml); |
335 | 342 |
436 { | 443 { |
437 xmlnode *ret; | 444 xmlnode *ret; |
438 xmlnode *child; | 445 xmlnode *child; |
439 xmlnode *sibling = NULL; | 446 xmlnode *sibling = NULL; |
440 | 447 |
441 if(!src) | 448 g_return_val_if_fail(src != NULL, NULL); |
442 return NULL; | |
443 | 449 |
444 ret = new_node(src->name, src->type); | 450 ret = new_node(src->name, src->type); |
445 if(src->data) { | 451 if(src->data) { |
446 if(src->data_sz) { | 452 if(src->data_sz) { |
447 ret->data = g_memdup(src->data, src->data_sz); | 453 ret->data = g_memdup(src->data, src->data_sz); |
460 sibling = ret->child; | 466 sibling = ret->child; |
461 } | 467 } |
462 sibling->parent = ret; | 468 sibling->parent = ret; |
463 } | 469 } |
464 | 470 |
471 ret->lastchild = sibling; | |
472 | |
465 return ret; | 473 return ret; |
466 } | 474 } |
467 | 475 |
468 xmlnode * | 476 xmlnode * |
469 xmlnode_get_next_twin(xmlnode *node) | 477 xmlnode_get_next_twin(xmlnode *node) |