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)