Re: b-a-s .server files & cold start ...



On 3/16/06, michael meeks <michael meeks novell com> wrote:
>         I think it's safe to say that a full-blown XML implementation is not
> really necessary for reading a few simple .server files; we should
> prolly switch to GMarkup.

While not necessary, I wouldn't be so certain about getting any more
performance out of GMarkup. I once wrote a silly benchmark for three
XML parsers (expat, libxml2, GMarkup) using empty callbacks, so any
time spent is because of the parser (application logic would be
virtually identical in all cases.)

See attachment. Usage: ./testxml [--mmap] anyfile.xml


--
Tommi Komulainen                                 tommi komulainen iki fi
/*
gcc -Wall -O2 -g `pkg-config --cflags --libs glib-2.0 libxml-2.0` -lexpat -o testxml testxml.c
*/
#include <glib.h>
#include <libxml/parser.h>
#include <expat.h>

#define DEFAULT_REPEAT 10

/************************************************************************
 * GMarkup
 */
static void start_element_gmarkup (GMarkupParseContext *ctxt, const gchar *name, const gchar **attnames, const gchar **attvals, gpointer user_data, GError **error) { } 
static void end_element_gmarkup (GMarkupParseContext *ctxt, const char *name, gpointer user_data, GError **error) { }
static void text_gmarkup (GMarkupParseContext *ctxt, const gchar *text, gsize text_len, gpointer user_data, GError **error) { }

static inline void
time_gmarkup (const char *text, gsize text_len)
{
	static const GMarkupParser parser = {
		.start_element = start_element_gmarkup,
		.end_element = end_element_gmarkup,
		.text = text_gmarkup,
	};
	GMarkupParseContext *ctxt;

	ctxt = g_markup_parse_context_new (&parser, 0, NULL, NULL);
	g_assert (ctxt != NULL);

	g_assert (g_markup_parse_context_parse (ctxt, text, text_len, NULL));
	g_assert (g_markup_parse_context_end_parse (ctxt, NULL));
	g_markup_parse_context_free (ctxt);
}

/************************************************************************
 * libxml2
 */
static void start_element_libxml (void *ctxt, const xmlChar *name, const xmlChar **atts) { }
static void end_element_libxml (void *ctxt, const xmlChar *name) { }
static void characters_libxml (void *ctxt, const xmlChar *ch, int len) { }

static inline void
time_libxml2 (const char *text, gsize text_len)
{
	static xmlSAXHandler parser = {
		.startElement = start_element_libxml,
		.endElement   = end_element_libxml,
		.characters   = characters_libxml
	};
	xmlParserCtxtPtr ctxt;

	ctxt = xmlCreatePushParserCtxt(&parser, NULL, text, 4, "");
	g_assert (ctxt != NULL);
	xmlParseChunk(ctxt, text+4, text_len-4, 1);
	xmlFreeParserCtxt(ctxt);
}

/************************************************************************
 * expat
 */
static void start_element_expat (void *userData, const XML_Char *name, const XML_Char **atts) { } 
static void end_element_expat (void *userData, const XML_Char *name) { } 
static void character_expat (void *userData, const XML_Char *s, int len) { }

static inline void
time_expat (const char *text, gsize text_len)
{
	XML_Parser parser;

	parser = XML_ParserCreate("UTF-8");
	XML_SetElementHandler(parser, start_element_expat, end_element_expat);
	XML_SetCharacterDataHandler(parser, character_expat);
	if (XML_Parse(parser, text, text_len, 1) != XML_STATUS_OK) {
		g_printerr("  %d:%d: %s\n",
			   XML_GetCurrentLineNumber(parser),
			   XML_GetCurrentColumnNumber(parser),
			   XML_ErrorString(XML_GetErrorCode(parser)));
		exit(1);
	}
	XML_ParserFree(parser);
}

#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int
main (int argc, char **argv)
{
	const char *filename;
	char       *text;
	gsize       text_len;
	GTimer     *timer;
	gboolean    use_mmap = FALSE;
	int         i;
	int         repeat;
	gdouble     elapsed;

	timer = g_timer_new ();

	++argv; --argc;

	if (argc > 1 && strcmp(*argv, "--mmap") == 0)
	{
		use_mmap = 1;
		++argv; --argc;
	}

	filename = *argv;

	++argv; --argc;

	if (argc > 0)
	{
		repeat = atoi(*argv);
		g_assert (repeat > 0);

		++argv; --argc;
	}
	else
		repeat = DEFAULT_REPEAT;

	if (use_mmap)
	{
		int          fd;
		struct stat  st;
		void        *mem;

		printf("using mmap\n");

		g_assert((fd = open(filename, O_RDONLY)) != -1);
		g_assert(fstat(fd, &st) == 0);
		g_assert((mem = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED);
		close(fd);
		
		text_len = st.st_size;
		text = mem;
	}
	else
	{
		printf("using memory buffer\n");
		g_assert (g_file_get_contents (filename, &text, &text_len, NULL));
	}


	printf("parser  cnt total    average\n");
	printf("GMarkup "); fflush(stdout);
	g_timer_start (timer);
	for (i = 0; i < repeat; i++)
		time_gmarkup(text, text_len);
	elapsed = g_timer_elapsed(timer, NULL);
	printf("%3d %.6f %.6f\n", repeat, elapsed, elapsed/repeat);

	printf("libxml2 "); fflush(stdout);
	g_timer_start (timer);
	for (i = 0; i < repeat; i++)
		time_libxml2(text, text_len);
	elapsed = g_timer_elapsed(timer, NULL);
	printf("%3d %.6f %.6f\n", repeat, elapsed, elapsed/repeat);

	printf("  expat "); fflush(stdout);
	g_timer_start (timer);
	for (i = 0; i < repeat; i++)
		time_expat(text, text_len);
	elapsed = g_timer_elapsed(timer, NULL);
	printf("%3d %.6f %.6f\n", repeat, elapsed, elapsed/repeat);

	return 0;
}






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]