From 9ea11fcad99d1add776c3a10266b485e940b226c Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Fri, 3 Mar 2023 17:02:37 -0500 Subject: [PATCH] ext: improve fidelity of XML::Document memsize and include test coverage for it --- ext/nokogiri/xml_document.c | 8 ++++++- test/test_memory_leak.rb | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/ext/nokogiri/xml_document.c b/ext/nokogiri/xml_document.c index 4b26cd4b6ec..d085b0a8ad9 100644 --- a/ext/nokogiri/xml_document.c +++ b/ext/nokogiri/xml_document.c @@ -89,12 +89,18 @@ dealloc(void *data) static size_t memsize_node(const xmlNodePtr node) { + /* note we don't count namespace definitions, just going for a good-enough number here */ xmlNodePtr child; size_t memsize = 0; for (child = node->children; child; child = child->next) { - /* This should count the properties too. */ memsize += sizeof(xmlNode) + memsize_node(child); } + /* xmlAttr and xmlNode share the same layout for next/prev/parent/etc. */ + for (child = (xmlNodePtr)node->properties; child; child = child->next) { + memsize += sizeof(xmlAttr) + memsize_node(child); + } + memsize += xmlStrlen(node->name); + memsize += xmlStrlen(node->content); return memsize; } diff --git a/test/test_memory_leak.rb b/test/test_memory_leak.rb index 808040d25a9..b77d796e9a2 100644 --- a/test/test_memory_leak.rb +++ b/test/test_memory_leak.rb @@ -272,6 +272,50 @@ def test_leaking_dtd_nodes_after_internal_subset_removal end end # if NOKOGIRI_GC + def test_object_space_memsize_of + begin + require "objspace" + rescue LoadError + skip("ObjectSpace not available") + end + + base_size = ObjectSpace.memsize_of(Nokogiri::XML(<<~XML)) + + asdf + + XML + + more_children_size = ObjectSpace.memsize_of(Nokogiri::XML(<<~XML)) + + asdf + asdf + asdf + + XML + assert(more_children_size > base_size, "adding children should increase memsize") + + attributes_size = ObjectSpace.memsize_of(Nokogiri::XML(<<~XML)) + + asdf + + XML + assert(attributes_size > base_size, "adding attributes should increase memsize") + + string_size = ObjectSpace.memsize_of(Nokogiri::XML(<<~XML)) + + asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf + + XML + assert(string_size > base_size, "longer strings should increase memsize") + + bigger_name_size = ObjectSpace.memsize_of(Nokogiri::XML(<<~XML)) + + asdf + + XML + assert(bigger_name_size > base_size, "longer tags should increase memsize") + end + module MemInfo # from https://stackoverflow.com/questions/7220896/get-current-ruby-process-memory-usage # this is only going to work on linux