From fe5faa2cc5dc50cd3d4338c5daa5c77a81e9e8f0 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Thu, 11 Feb 2010 13:38:12 -0800 Subject: [PATCH] Remove tracing (--enable-trace). Remove all functionality related to tracing. This functionality was useful for understanding memory fragmentation during early algorithmic design of jemalloc, but it had little utility for non-trivial applications, due to the sheer volume of data written to disk. --- jemalloc/Makefile.in | 13 +- jemalloc/configure.ac | 52 - jemalloc/doc/jemalloc.3.in | 35 - jemalloc/src/internal/jemalloc_arena.h | 7 - jemalloc/src/internal/jemalloc_internal.h.in | 8 +- jemalloc/src/internal/jemalloc_trace.h | 32 - jemalloc/src/internal/mtrgraph_defs.h.in | 14 - jemalloc/src/internal/mtrplay_defs.h.in | 14 - jemalloc/src/jemalloc.c | 86 +- jemalloc/src/jemalloc_arena.c | 43 - jemalloc/src/jemalloc_ctl.c | 17 - jemalloc/src/jemalloc_defs.h.in | 3 - jemalloc/src/jemalloc_stats.c | 2 - jemalloc/src/jemalloc_trace.c | 281 ----- jemalloc/src/jemtr2mtr.c | 12 - jemalloc/src/mtrgraph.c | 1054 ------------------ jemalloc/src/mtrplay.c | 225 ---- 17 files changed, 13 insertions(+), 1885 deletions(-) delete mode 100644 jemalloc/src/internal/jemalloc_trace.h delete mode 100644 jemalloc/src/internal/mtrgraph_defs.h.in delete mode 100644 jemalloc/src/internal/mtrplay_defs.h.in delete mode 100644 jemalloc/src/jemalloc_trace.c delete mode 100644 jemalloc/src/jemtr2mtr.c delete mode 100644 jemalloc/src/mtrgraph.c delete mode 100644 jemalloc/src/mtrplay.c diff --git a/jemalloc/Makefile.in b/jemalloc/Makefile.in index 050df0ce..b946f8ec 100644 --- a/jemalloc/Makefile.in +++ b/jemalloc/Makefile.in @@ -24,7 +24,6 @@ CFLAGS += -dynamic endif LDFLAGS := @LDFLAGS@ LIBS := @LIBS@ -GDLIBS := @GDLIBS@ RPATH_EXTRA := @RPATH_EXTRA@ ifeq (macho, @abi@) SO := dylib @@ -34,7 +33,6 @@ endif REV := 0 # Lists of files. -BINS := @bins@ CHDRS := @objroot@src/jemalloc@install_suffix@.h \ @objroot@src/jemalloc_defs@install_suffix@.h CSRCS := @srcroot@src/jemalloc.c @srcroot@src/jemalloc_arena.c \ @@ -44,8 +42,7 @@ CSRCS := @srcroot@src/jemalloc.c @srcroot@src/jemalloc_arena.c \ @srcroot@src/jemalloc_ctl.c @srcroot@src/jemalloc_extent.c \ @srcroot@src/hash.c @srcroot@src/jemalloc_huge.c @srcroot@src/mb.c \ @srcroot@src/jemalloc_mutex.c @srcroot@src/prof.c \ - @srcroot@src/jemalloc_stats.c @srcroot@src/jemalloc_tcache.c \ - @srcroot@src/jemalloc_trace.c + @srcroot@src/jemalloc_stats.c @srcroot@src/jemalloc_tcache.c DSOS := @objroot@lib/libjemalloc@install_suffix@.so.$(REV) \ @objroot@lib/libjemalloc@install_suffix@.so \ @objroot@lib/libjemalloc@install_suffix@_pic.a @@ -54,7 +51,7 @@ MAN3 := @objroot@doc/jemalloc@install_suffix@.3 .PHONY: all dist install check clean distclean relclean # Default target. -all: $(DSOS) bins +all: $(DSOS) # # Include generated dependency files. @@ -71,12 +68,6 @@ $(DSOS): $(CSRCS:@srcroot@%.c=@objroot@%.o) ln -sf libjemalloc@install_suffix@.so.$(REV) lib/libjemalloc@install_suffix@.so ar crus @objroot@lib/libjemalloc@install_suffix@_pic.a $+ -bins: $(BINS) - -@objroot@bin/mtrgraph@install_suffix@: @objroot@src/mtrgraph.o - @mkdir -p $(@D) - $(CC) -o $@ $< $(LDFLAGS) $(LIBS) $(GDLIBS) - @objroot@bin/%@install_suffix@: @objroot@src/%.o @mkdir -p $(@D) $(CC) -o $@ $< $(LDFLAGS) $(LIBS) diff --git a/jemalloc/configure.ac b/jemalloc/configure.ac index b6ded7bc..ac3f32b1 100644 --- a/jemalloc/configure.ac +++ b/jemalloc/configure.ac @@ -275,16 +275,10 @@ cfgoutputs_tup="${cfgoutputs_tup} src/jemalloc${install_suffix}.h:src/jemalloc.h cfgoutputs_tup="${cfgoutputs_tup} src/internal/jemalloc_internal.h" cfghdrs_in="src/jemalloc_defs.h.in" -cfghdrs_in="${cfghdrs_in} src/internal/mtrgraph_defs.h.in" -cfghdrs_in="${cfghdrs_in} src/internal/mtrplay_defs.h.in" cfghdrs_out="src/jemalloc_defs${install_suffix}.h" -cfghdrs_out="${cfghdrs_out} src/internal/mtrgraph_defs.h" -cfghdrs_out="${cfghdrs_out} src/internal/mtrplay_defs.h" cfghdrs_tup="src/jemalloc_defs${install_suffix}.h:src/jemalloc_defs.h.in" -cfghdrs_tup="${cfghdrs_tup} src/internal/mtrgraph_defs.h" -cfghdrs_tup="${cfghdrs_tup} src/internal/mtrplay_defs.h" dnl Do not compile with debugging by default. AC_ARG_ENABLE([debug], @@ -340,28 +334,6 @@ else fi AC_SUBST([roff_stats]) -dnl Do not enable tracing by default. -AC_ARG_ENABLE([trace], - [AS_HELP_STRING([--enable-trace], [Enable allocation tracing (logging)])], -[if test "x$enable_trace" = "xno" ; then - enable_trace="0" -else - enable_trace="1" -fi -], -[enable_trace="0"] -) -if test "x$enable_trace" = "x1" ; then - AC_DEFINE([JEMALLOC_TRACE], [ ]) -fi -AC_SUBST([enable_trace]) -if test "x$enable_trace" = "x0" ; then - roff_trace=".\\\" " -else - roff_trace="" -fi -AC_SUBST([roff_trace]) - dnl Do not enable profiling by default. AC_ARG_ENABLE([prof], [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])], @@ -708,27 +680,6 @@ if test "x$enable_prof" = "x1" -a "x$enable_prof_libunwind" = "x0" \ fi fi -dnl ============================================================================ -dnl Configure libgd for mtrgraph. -bins="${objroot}bin/jemtr2mtr${install_suffix}" -bins="${bins} ${objroot}bin/mtrplay${install_suffix}" -GDLIBS="" - -have_libgd="yes" -AC_CHECK_HEADERS([gd.h], , [have_libgd="no"]) -AC_CHECK_HEADERS([gdfontt.h], , [have_libgd="no"]) -AC_CHECK_HEADERS([gdfonts.h], , [have_libgd="no"]) -AC_CHECK_HEADERS([gdfontmb.h], , [have_libgd="no"]) -AC_CHECK_HEADERS([gdfontl.h], , [have_libgd="no"]) -AC_CHECK_HEADERS([gdfontg.h], , [have_libgd="no"]) -AC_CHECK_LIB([gd], [gdImageCreate], [GDLIBS="-lgd"], [have_libgd="no"]) - -if test "x${have_libgd}" = "xyes" ; then - bins="${bins} ${objroot}bin/mtrgraph${install_suffix}" -fi -AC_SUBST([bins]) -AC_SUBST([GDLIBS]) - dnl ============================================================================ dnl Check for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL @@ -769,14 +720,11 @@ AC_MSG_RESULT([abs_srcroot : ${abs_srcroot}]) AC_MSG_RESULT([objroot : ${objroot}]) AC_MSG_RESULT([abs_objroot : ${abs_objroot}]) AC_MSG_RESULT([]) -AC_MSG_RESULT([bins : ${bins}]) -AC_MSG_RESULT([]) AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}]) AC_MSG_RESULT([install_suffix : ${install_suffix}]) AC_MSG_RESULT([autogen : ${enable_autogen}]) AC_MSG_RESULT([debug : ${enable_debug}]) AC_MSG_RESULT([stats : ${enable_stats}]) -AC_MSG_RESULT([trace : ${enable_trace}]) AC_MSG_RESULT([prof : ${enable_prof}]) AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}]) AC_MSG_RESULT([tiny : ${enable_tiny}]) diff --git a/jemalloc/doc/jemalloc.3.in b/jemalloc/doc/jemalloc.3.in index 4266382f..d314fb0a 100644 --- a/jemalloc/doc/jemalloc.3.in +++ b/jemalloc/doc/jemalloc.3.in @@ -464,21 +464,6 @@ Double/halve the size of the maximum size class that is a multiple of the quantum (8 or 16 bytes, depending on architecture). Above this size, cacheline spacing is used for size classes. The default value is 128 bytes. -@roff_trace@.It T -@roff_trace@Write a verbose trace log to a set of files named according to the -@roff_trace@pattern -@roff_trace@.Pa jemtr.. -@roff_trace@for all allocation operations. -@roff_trace@The result can be converted from -@roff_trace@.Nm jemtr -@roff_trace@to -@roff_trace@.Nm mtr -@roff_trace@format via -@roff_trace@.Xr jemtr2mtr 1 , -@roff_trace@the output of which can be used by -@roff_trace@.Xr mtrplay 1 -@roff_trace@and -@roff_trace@.Xr mtrgraph 1 . @roff_prof@.It U @roff_prof@Trigger a memory profile dump every time the total virtual memory @roff_prof@exceeds the previous maximum. @@ -737,11 +722,6 @@ This is useful for detecting whether another thread caused a refresh. --disable-tls was not specified during build configuration. .Ed .\"----------------------------------------------------------------------------- -.It Sy "config.trace (bool) r-" -.Bd -ragged -offset indent -compact ---enable-trace was specified during build configuration. -.Ed -.\"----------------------------------------------------------------------------- .It Sy "config.xmalloc (bool) r-" .Bd -ragged -offset indent -compact --enable-xmalloc was specified during build configuration. @@ -831,13 +811,6 @@ option. @roff_prof@option. @roff_prof@.Ed .\"----------------------------------------------------------------------------- -@roff_trace@.It Sy "opt.trace (bool) r-" -@roff_trace@.Bd -ragged -offset indent -compact -@roff_trace@See the -@roff_trace@.Dq T -@roff_trace@option. -@roff_trace@.Ed -.\"----------------------------------------------------------------------------- .It Sy "opt.lg_qspace_max (size_t) r-" .Bd -ragged -offset indent -compact See the @@ -1301,11 +1274,6 @@ options and symbols for debugger support. @roff_fill@.Dq J @roff_fill@option may help provoke the problem. @roff_fill@.Pp -@roff_trace@In truly difficult cases, the -@roff_trace@.Dq T -@roff_trace@option can provide a detailed trace of all calls made to these -@roff_trace@functions. -@roff_trace@.Pp Unfortunately this implementation does not provide much detail about the problems it detects; the performance impact for storing such information would be prohibitive. @@ -1460,9 +1428,6 @@ To specify in the source a chunk size that is twice the default: @jemalloc_prefix@malloc_options = "K"; .Ed .Sh SEE ALSO -.Xr mtrgraph 1 , -.Xr mtrplay 1 , -.Xr jemtr2mtr 1 , .Xr madvise 2 , .Xr mmap 2 , @roff_dss@.Xr sbrk 2 , diff --git a/jemalloc/src/internal/jemalloc_arena.h b/jemalloc/src/internal/jemalloc_arena.h index cba954f2..5596c17f 100644 --- a/jemalloc/src/internal/jemalloc_arena.h +++ b/jemalloc/src/internal/jemalloc_arena.h @@ -283,13 +283,6 @@ struct arena_s { # endif #endif -#ifdef JEMALLOC_TRACE -# define TRACE_BUF_SIZE 65536 - unsigned trace_buf_end; - char trace_buf[TRACE_BUF_SIZE]; - int trace_fd; -#endif - #ifdef JEMALLOC_PROF uint64_t prof_accumbytes; #endif diff --git a/jemalloc/src/internal/jemalloc_internal.h.in b/jemalloc/src/internal/jemalloc_internal.h.in index 8f52fa3f..d35cdaf2 100644 --- a/jemalloc/src/internal/jemalloc_internal.h.in +++ b/jemalloc/src/internal/jemalloc_internal.h.in @@ -58,8 +58,8 @@ extern void (*JEMALLOC_P(malloc_message))(void *w4opaque, const char *p1, #endif /* - * jemalloc can conceptually be broken into components (arena, tcache, trace, - * etc.), but there are circular dependencies that cannot be broken without + * jemalloc can conceptually be broken into components (arena, tcache, etc.), + * but there are circular dependencies that cannot be broken without * substantial performance degradation. In order to reduce the effect on * visual code flow, read the header files in multiple passes, with one of the * following cpp variables defined during each pass: @@ -181,7 +181,6 @@ extern void (*JEMALLOC_P(malloc_message))(void *w4opaque, const char *p1, #include "internal/jemalloc_chunk.h" #include "internal/jemalloc_huge.h" #include "internal/jemalloc_tcache.h" -#include "internal/jemalloc_trace.h" #include "internal/hash.h" #include "internal/prof.h" @@ -201,7 +200,6 @@ extern void (*JEMALLOC_P(malloc_message))(void *w4opaque, const char *p1, #include "internal/jemalloc_chunk.h" #include "internal/jemalloc_huge.h" #include "internal/jemalloc_tcache.h" -#include "internal/jemalloc_trace.h" #include "internal/hash.h" #include "internal/prof.h" @@ -264,7 +262,6 @@ arena_t *choose_arena_hard(void); #include "internal/jemalloc_chunk.h" #include "internal/jemalloc_huge.h" #include "internal/jemalloc_tcache.h" -#include "internal/jemalloc_trace.h" #include "internal/hash.h" #include "internal/prof.h" @@ -372,7 +369,6 @@ choose_arena(void) #include "internal/jemalloc_tcache.h" #include "internal/jemalloc_arena.h" -#include "internal/jemalloc_trace.h" #include "internal/hash.h" #include "internal/prof.h" diff --git a/jemalloc/src/internal/jemalloc_trace.h b/jemalloc/src/internal/jemalloc_trace.h deleted file mode 100644 index e474ed03..00000000 --- a/jemalloc/src/internal/jemalloc_trace.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifdef JEMALLOC_TRACE -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -extern bool opt_trace; - -void trace_malloc(const void *ptr, size_t size); -void trace_calloc(const void *ptr, size_t number, size_t size); -void trace_posix_memalign(const void *ptr, size_t alignment, size_t size); -void trace_realloc(const void *ptr, const void *old_ptr, size_t size, - size_t old_size); -void trace_free(const void *ptr, size_t size); -void trace_malloc_usable_size(size_t size, const void *ptr); -void trace_thread_exit(void); - -bool trace_boot(void); - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ -#endif /* JEMALLOC_TRACE */ diff --git a/jemalloc/src/internal/mtrgraph_defs.h.in b/jemalloc/src/internal/mtrgraph_defs.h.in deleted file mode 100644 index 7a81e3c7..00000000 --- a/jemalloc/src/internal/mtrgraph_defs.h.in +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef MTRGRAPH_DEFS_H_ -#define MTRGRAPH_DEFS_H_ - -/* Defined if __attribute__((...)) syntax is supported. */ -#undef JEMALLOC_HAVE_ATTR -#ifdef JEMALLOC_HAVE_ATTR -# define JEMALLOC_ATTR(s) __attribute__((s)) -#else -# define JEMALLOC_ATTR(s) -#endif - -#undef JEMALLOC_DEBUG - -#endif /* MTRGRAPH_DEFS_H_ */ diff --git a/jemalloc/src/internal/mtrplay_defs.h.in b/jemalloc/src/internal/mtrplay_defs.h.in deleted file mode 100644 index 8b62625f..00000000 --- a/jemalloc/src/internal/mtrplay_defs.h.in +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef MTRPLAY_DEFS_H_ -#define MTRPLAY_DEFS_H_ - -/* Defined if __attribute__((...)) syntax is supported. */ -#undef JEMALLOC_HAVE_ATTR -#ifdef JEMALLOC_HAVE_ATTR -# define JEMALLOC_ATTR(s) __attribute__((s)) -#else -# define JEMALLOC_ATTR(s) -#endif - -#undef JEMALLOC_DEBUG - -#endif /* MTRPLAY_DEFS_H_ */ diff --git a/jemalloc/src/jemalloc.c b/jemalloc/src/jemalloc.c index 813f50b5..dfff7424 100644 --- a/jemalloc/src/jemalloc.c +++ b/jemalloc/src/jemalloc.c @@ -581,14 +581,6 @@ MALLOC_OUT: opt_lg_cspace_max) opt_lg_qspace_max++; break; -#ifdef JEMALLOC_TRACE - case 't': - opt_trace = false; - break; - case 'T': - opt_trace = true; - break; -#endif #ifdef JEMALLOC_PROF case 'u': opt_prof_udump = false; @@ -650,14 +642,6 @@ MALLOC_OUT: return (true); } -#ifdef JEMALLOC_TRACE - if (opt_trace) { - if (trace_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } - } -#endif if (opt_stats_print) { /* Print statistics at exit. */ if (atexit(stats_print_atexit) != 0) { @@ -913,10 +897,6 @@ RETURN: #ifdef JEMALLOC_PROF if (opt_prof && ret != NULL) prof_malloc(ret, cnt); -#endif -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_malloc(ret, size); #endif return (ret); } @@ -1004,10 +984,6 @@ RETURN: #ifdef JEMALLOC_PROF if (opt_prof && result != NULL) prof_malloc(result, cnt); -#endif -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_posix_memalign(result, alignment, size); #endif return (ret); } @@ -1078,10 +1054,6 @@ RETURN: #ifdef JEMALLOC_PROF if (opt_prof && ret != NULL) prof_malloc(ret, cnt); -#endif -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_calloc(ret, num, size); #endif return (ret); } @@ -1091,28 +1063,11 @@ void * JEMALLOC_P(realloc)(void *ptr, size_t size) { void *ret; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_TRACE)) +#ifdef JEMALLOC_PROF size_t old_size; -#endif -#ifdef JEMALLOC_PROF prof_thr_cnt_t *cnt, *old_cnt; #endif -/* - * Both profiling and tracing may need old_size, and the conditional logic for - * deciding whether to call isalloc() is messy. Define need_old_size here in - * order to avoid repeated nasty cpp conditional logic. - */ -#ifdef JEMALLOC_PROF -# ifdef JEMALLOC_TRACE -# define need_old_size opt_prof || opt_trace -# else -# define need_old_size opt_prof -# endif -#elif (defined(JEMALLOC_TRACE)) -# define need_old_size opt_trace -#endif - if (size == 0) { #ifdef JEMALLOC_SYSV if (opt_sysv == false) @@ -1121,24 +1076,20 @@ JEMALLOC_P(realloc)(void *ptr, size_t size) #ifdef JEMALLOC_SYSV else { if (ptr != NULL) { -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_TRACE)) - if (need_old_size) { +#ifdef JEMALLOC_PROF + if (opt_prof) { old_size = isalloc(ptr); -# ifdef JEMALLOC_PROF old_cnt = prof_cnt_get(ptr); cnt = NULL; -# endif } #endif idalloc(ptr); } -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_TRACE)) - else if (need_old_size) { +#ifdef JEMALLOC_PROF + else if (opt_prof) { old_size = 0; -# ifdef JEMALLOC_PROF old_cnt = NULL; cnt = NULL; -# endif } #endif ret = NULL; @@ -1151,16 +1102,14 @@ JEMALLOC_P(realloc)(void *ptr, size_t size) assert(malloc_initialized || malloc_initializer == pthread_self()); -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_TRACE)) - if (need_old_size) { +#ifdef JEMALLOC_PROF + if (opt_prof) { old_size = isalloc(ptr); -# ifdef JEMALLOC_PROF old_cnt = prof_cnt_get(ptr); if ((cnt = prof_alloc_prep()) == NULL) { ret = NULL; goto OOM; } -# endif } #endif @@ -1181,12 +1130,10 @@ OOM: errno = ENOMEM; } } else { -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_TRACE)) - if (need_old_size) { +#ifdef JEMALLOC_PROF + if (opt_prof) { old_size = 0; -# ifdef JEMALLOC_PROF old_cnt = NULL; -# endif } #endif if (malloc_init()) { @@ -1220,18 +1167,11 @@ OOM: #ifdef JEMALLOC_SYSV RETURN: #endif -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_realloc(ret, ptr, size, old_size); -#endif #ifdef JEMALLOC_PROF if (opt_prof) prof_realloc(ret, cnt, ptr, old_size, old_cnt); #endif return (ret); -#ifdef need_old_size -# undef need_old_size -#endif } JEMALLOC_ATTR(visibility("default")) @@ -1246,10 +1186,6 @@ JEMALLOC_P(free)(void *ptr) #ifdef JEMALLOC_PROF if (opt_prof) prof_free(ptr); -#endif -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_free(ptr, isalloc(ptr)); #endif idalloc(ptr); } @@ -1272,10 +1208,6 @@ JEMALLOC_P(malloc_usable_size)(const void *ptr) assert(ptr != NULL); ret = isalloc(ptr); -#ifdef JEMALLOC_TRACE - if (opt_trace) - trace_malloc_usable_size(ret, ptr); -#endif return (ret); } diff --git a/jemalloc/src/jemalloc_arena.c b/jemalloc/src/jemalloc_arena.c index 585be3d6..c3dc3829 100644 --- a/jemalloc/src/jemalloc_arena.c +++ b/jemalloc/src/jemalloc_arena.c @@ -2023,49 +2023,6 @@ arena_new(arena_t *arena, unsigned ind) # endif #endif -#ifdef JEMALLOC_TRACE - if (opt_trace) { - /* "jemtr.." */ - char buf[UMAX2S_BUFSIZE]; - char filename[6 + UMAX2S_BUFSIZE + 1 + UMAX2S_BUFSIZE + 1]; - char *s; - unsigned i, slen; - - arena->trace_buf_end = 0; - - i = 0; - - s = "jemtr."; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = umax2s(getpid(), 10, buf); - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = "."; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = umax2s(ind, 10, buf); - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - filename[i] = '\0'; - - arena->trace_fd = creat(filename, 0644); - if (arena->trace_fd == -1) { - malloc_write4("", - ": creat(\"", filename, "\", 0644) failed\n"); - abort(); - } - } -#endif - #ifdef JEMALLOC_PROF arena->prof_accumbytes = 0; #endif diff --git a/jemalloc/src/jemalloc_ctl.c b/jemalloc/src/jemalloc_ctl.c index a68e78a6..9775f72d 100644 --- a/jemalloc/src/jemalloc_ctl.c +++ b/jemalloc/src/jemalloc_ctl.c @@ -48,7 +48,6 @@ CTL_PROTO(config_sysv) CTL_PROTO(config_tcache) CTL_PROTO(config_tiny) CTL_PROTO(config_tls) -CTL_PROTO(config_trace) CTL_PROTO(config_xmalloc) CTL_PROTO(opt_abort) #ifdef JEMALLOC_FILL @@ -75,9 +74,6 @@ CTL_PROTO(opt_prof_udump) CTL_PROTO(opt_prof_leak) #endif CTL_PROTO(opt_stats_print) -#ifdef JEMALLOC_TRACE -CTL_PROTO(opt_trace) -#endif CTL_PROTO(opt_lg_qspace_max) CTL_PROTO(opt_lg_cspace_max) CTL_PROTO(opt_lg_medium_max) @@ -214,7 +210,6 @@ static const ctl_node_t config_node[] = { {NAME("tcache"), CTL(config_tcache)}, {NAME("tiny"), CTL(config_tiny)}, {NAME("tls"), CTL(config_tls)}, - {NAME("trace"), CTL(config_trace)}, {NAME("xmalloc"), CTL(config_xmalloc)} }; @@ -244,9 +239,6 @@ static const ctl_node_t opt_node[] = { {NAME("prof_leak"), CTL(opt_prof_leak)}, #endif {NAME("stats_print"), CTL(opt_stats_print)}, -#ifdef JEMALLOC_TRACE - {NAME("trace"), CTL(opt_trace)}, -#endif {NAME("lg_qspace_max"), CTL(opt_lg_qspace_max)}, {NAME("lg_cspace_max"), CTL(opt_lg_cspace_max)}, {NAME("lg_medium_max"), CTL(opt_lg_medium_max)}, @@ -1046,12 +1038,6 @@ CTL_RO_TRUE_GEN(config_tls) CTL_RO_FALSE_GEN(config_tls) #endif -#ifdef JEMALLOC_TRACE -CTL_RO_TRUE_GEN(config_trace) -#else -CTL_RO_FALSE_GEN(config_trace) -#endif - #ifdef JEMALLOC_XMALLOC CTL_RO_TRUE_GEN(config_xmalloc) #else @@ -1085,9 +1071,6 @@ CTL_RO_GEN(opt_prof_udump, opt_prof_udump, bool) CTL_RO_GEN(opt_prof_leak, opt_prof_leak, bool) #endif CTL_RO_GEN(opt_stats_print, opt_stats_print, bool) -#ifdef JEMALLOC_TRACE -CTL_RO_GEN(opt_trace, opt_trace, bool) -#endif CTL_RO_GEN(opt_lg_qspace_max, opt_lg_qspace_max, size_t) CTL_RO_GEN(opt_lg_cspace_max, opt_lg_cspace_max, size_t) CTL_RO_GEN(opt_lg_medium_max, opt_lg_medium_max, size_t) diff --git a/jemalloc/src/jemalloc_defs.h.in b/jemalloc/src/jemalloc_defs.h.in index 942694f4..4b4ea7d0 100644 --- a/jemalloc/src/jemalloc_defs.h.in +++ b/jemalloc/src/jemalloc_defs.h.in @@ -45,9 +45,6 @@ /* JEMALLOC_STATS enables statistics calculation. */ #undef JEMALLOC_STATS -/* JEMALLOC_TRACE enables allocation tracing. */ -#undef JEMALLOC_TRACE - /* JEMALLOC_PROF enables allocation profiling. */ #undef JEMALLOC_PROF diff --git a/jemalloc/src/jemalloc_stats.c b/jemalloc/src/jemalloc_stats.c index 54aa103b..7a7f111e 100644 --- a/jemalloc/src/jemalloc_stats.c +++ b/jemalloc/src/jemalloc_stats.c @@ -440,8 +440,6 @@ stats_print(void (*write4)(void *, const char *, const char *, const char *, if ((err = mallctl("opt.overcommit", &bv, &bsz, NULL, 0)) == 0) write4(w4opaque, bv ? "O" : "o", "", "", ""); write4(w4opaque, "P", "", "", ""); - if ((err = mallctl("opt.trace", &bv, &bsz, NULL, 0)) == 0) - write4(w4opaque, bv ? "T" : "t", "", "", ""); if ((err = mallctl("opt.prof_udump", &bv, &bsz, NULL, 0)) == 0) write4(w4opaque, bv ? "U" : "u", "", "", ""); if ((err = mallctl("opt.sysv", &bv, &bsz, NULL, 0)) == 0) diff --git a/jemalloc/src/jemalloc_trace.c b/jemalloc/src/jemalloc_trace.c deleted file mode 100644 index a2146f57..00000000 --- a/jemalloc/src/jemalloc_trace.c +++ /dev/null @@ -1,281 +0,0 @@ -#define JEMALLOC_TRACE_C_ -#include "internal/jemalloc_internal.h" -#ifdef JEMALLOC_TRACE -/******************************************************************************/ -/* Data. */ - -bool opt_trace = false; - -static malloc_mutex_t trace_mtx; -static unsigned trace_next_tid = 1; - -static unsigned __thread trace_tid - JEMALLOC_ATTR(tls_model("initial-exec")); -/* Used to cause trace_cleanup() to be called. */ -static pthread_key_t trace_tsd; - -/******************************************************************************/ -/* Function prototypes for non-inline static functions. */ - -static arena_t *trace_arena(const void *ptr); -static void trace_flush(arena_t *arena); -static void trace_write(arena_t *arena, const char *s); -static unsigned trace_get_tid(void); -static void trace_thread_cleanup(void *arg); -static void malloc_trace_flush_all(void); - -/******************************************************************************/ - -static arena_t * -trace_arena(const void *ptr) -{ - arena_t *arena; - arena_chunk_t *chunk; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if ((void *)chunk == ptr) - arena = arenas[0]; - else - arena = chunk->arena; - - return (arena); -} - -static void -trace_flush(arena_t *arena) -{ - ssize_t err; - - err = write(arena->trace_fd, arena->trace_buf, arena->trace_buf_end); - if (err == -1) { - malloc_write4("", - ": write() failed during trace flush", "\n", ""); - if (opt_abort) - abort(); - } - arena->trace_buf_end = 0; -} - -static void -trace_write(arena_t *arena, const char *s) -{ - unsigned i, slen, n; - - i = 0; - slen = strlen(s); - while (i < slen) { - /* Flush the trace buffer if it is full. */ - if (arena->trace_buf_end == TRACE_BUF_SIZE) - trace_flush(arena); - - if (arena->trace_buf_end + slen <= TRACE_BUF_SIZE) { - /* Finish writing. */ - n = slen - i; - } else { - /* Write as much of s as will fit. */ - n = TRACE_BUF_SIZE - arena->trace_buf_end; - } - memcpy(&arena->trace_buf[arena->trace_buf_end], &s[i], n); - arena->trace_buf_end += n; - i += n; - } -} - -static unsigned -trace_get_tid(void) -{ - unsigned ret = trace_tid; - - if (ret == 0) { - malloc_mutex_lock(&trace_mtx); - trace_tid = trace_next_tid; - trace_next_tid++; - malloc_mutex_unlock(&trace_mtx); - ret = trace_tid; - - /* - * Set trace_tsd to non-zero so that the cleanup function will - * be called upon thread exit. - */ - pthread_setspecific(trace_tsd, (void *)ret); - } - - return (ret); -} - -static void -malloc_trace_flush_all(void) -{ - unsigned i; - - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) { - malloc_mutex_lock(&arenas[i]->lock); - trace_flush(arenas[i]); - malloc_mutex_unlock(&arenas[i]->lock); - } - } -} - -void -trace_malloc(const void *ptr, size_t size) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " m 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(size, 10, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_calloc(const void *ptr, size_t number, size_t size) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " c 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(number, 10, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(size, 10, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_posix_memalign(const void *ptr, size_t alignment, size_t size) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " a 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(alignment, 10, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(size, 10, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_realloc(const void *ptr, const void *old_ptr, size_t size, - size_t old_size) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " r 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, " 0x"); - trace_write(arena, umax2s((uintptr_t)old_ptr, 16, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(size, 10, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(old_size, 10, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_free(const void *ptr, size_t size) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " f 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, " "); - trace_write(arena, umax2s(isalloc(ptr), 10, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_malloc_usable_size(size_t size, const void *ptr) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = trace_arena(ptr); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " s "); - trace_write(arena, umax2s(size, 10, buf)); - trace_write(arena, " 0x"); - trace_write(arena, umax2s((uintptr_t)ptr, 16, buf)); - trace_write(arena, "\n"); - - malloc_mutex_unlock(&arena->lock); -} - -void -trace_thread_exit(void) -{ - char buf[UMAX2S_BUFSIZE]; - arena_t *arena = choose_arena(); - - malloc_mutex_lock(&arena->lock); - - trace_write(arena, umax2s(trace_get_tid(), 10, buf)); - trace_write(arena, " x\n"); - - malloc_mutex_unlock(&arena->lock); -} - -static void -trace_thread_cleanup(void *arg) -{ - - trace_thread_exit(); -} - -bool -trace_boot(void) -{ - - if (malloc_mutex_init(&trace_mtx)) - return (true); - - /* Flush trace buffers at exit. */ - if (atexit(malloc_trace_flush_all) != 0) { - malloc_write4("", ": Error in atexit()\n", "", ""); - if (opt_abort) - abort(); - } - /* Receive thread exit notifications. */ - if (pthread_key_create(&trace_tsd, trace_thread_cleanup) != 0) { - malloc_write4("", - ": Error in pthread_key_create()\n", "", ""); - abort(); - } - - return (false); -} -/******************************************************************************/ -#endif /* JEMALLOC_TRACE */ diff --git a/jemalloc/src/jemtr2mtr.c b/jemalloc/src/jemtr2mtr.c deleted file mode 100644 index 3361ae15..00000000 --- a/jemalloc/src/jemtr2mtr.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -int -main(int argc, char **argv) -{ - // XXX Parse a jemtr trace and convert it to a mtr trace. - fprintf(stderr, "XXX Not implemented\n"); - abort(); - - return 0; -} diff --git a/jemalloc/src/mtrgraph.c b/jemalloc/src/mtrgraph.c deleted file mode 100644 index c5f9dd31..00000000 --- a/jemalloc/src/mtrgraph.c +++ /dev/null @@ -1,1054 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "internal/mtrgraph_defs.h" -#ifndef JEMALLOC_DEBUG -# define NDEBUG -#endif -#include -#include "internal/rb.h" - -typedef struct -{ - // malloc: {0, size, addr} - // realloc: {oldAddr, size, addr} - // free: {oldAddr, 0, 0} - uintptr_t oldAddr; - size_t size; - uintptr_t addr; -} TraceRecord; - -typedef struct -{ - TraceRecord *trace; - uint64_t traceLen; -} Trace; - -typedef struct AllocationCacheRecordStruct AllocationCacheRecord; -struct AllocationCacheRecordStruct -{ - rb_node(AllocationCacheRecord) link; - - uint64_t addr; - uint64_t size; -}; -typedef rb_tree(AllocationCacheRecord) AllocationCache; - -int -cacheComp(AllocationCacheRecord *a, AllocationCacheRecord *b) -{ - if (a->addr < b->addr) - { - return -1; - } - else if (a->addr > b->addr) - { - return 1; - } - else - { - return 0; - } -} - -rb_wrap(static JEMALLOC_ATTR(unused), cache_tree_, AllocationCache, - AllocationCacheRecord, link, cacheComp) - -// Parse utrace records. Following are prototypical examples of each type of -// record: -// -// :utrace: 31532 malloc_init() -// :utrace: 31532 0x800b01000 = malloc(34816) -// :utrace: 31532 free(0x800b0a400) -// :utrace: 31532 0x800b35230 = realloc(0x800b35230, 45) -Trace * -parseInput(FILE *infile, uint64_t pastEvent) -{ - Trace *rVal; - uint64_t maxLen; - int result; - char buf[128]; - unsigned pid; - void *addr, *oldAddr; - size_t size; - - rVal = (Trace *) malloc(sizeof(Trace)); - if (rVal == NULL) - { - fprintf(stderr, "mtrgraph: Error in malloc()\n"); - goto RETURN; - } - - maxLen = 1024; - rVal->trace = (TraceRecord *) malloc(maxLen * sizeof(TraceRecord)); - if (rVal->trace == NULL) - { - fprintf(stderr, "mtrgraph: Error in malloc()\n"); - free(rVal); - rVal = NULL; - goto RETURN; - } - - rVal->traceLen = 0; - while (rVal->traceLen < pastEvent) - { - // Expand trace buffer, if necessary. - if (rVal->traceLen == maxLen) - { - TraceRecord *t; - - maxLen *= 2; - t = (TraceRecord *) realloc(rVal->trace, - maxLen * sizeof(TraceRecord)); - if (t == NULL) - { - fprintf(stderr, "mtrgraph: Error in realloc()\n"); - free(rVal->trace); - free(rVal); - rVal = NULL; - goto RETURN; - } - rVal->trace = t; - } - - // Get a line of input. - { - int c; - unsigned i; - - for (i = 0; i < sizeof(buf) - 1; i++) - { - c = fgetc(infile); - switch (c) - { - case EOF: - { - goto RETURN; - } - case '\n': - { - buf[i] = '\0'; - goto OUT; - } - default: - { - buf[i] = c; - break; - } - } - } - OUT:; - } - - // realloc? - result = sscanf(buf, ":utrace: %u %p = realloc(%p, %zu)", - &pid, &addr, &oldAddr, &size); - if (result == 4) - { - rVal->trace[rVal->traceLen].oldAddr = (uintptr_t) oldAddr; - rVal->trace[rVal->traceLen].size = size; - rVal->trace[rVal->traceLen].addr = (uintptr_t) addr; - - rVal->traceLen++; - continue; - } - - // malloc? - result = sscanf(buf, ":utrace: %u %p = malloc(%zu)", - &pid, &addr, &size); - if (result == 3) - { - rVal->trace[rVal->traceLen].oldAddr = (uintptr_t) NULL; - rVal->trace[rVal->traceLen].size = size; - rVal->trace[rVal->traceLen].addr = (uintptr_t) addr; - - rVal->traceLen++; - continue; - } - - // free? - result = sscanf(buf, ":utrace: %u free(%p)", - &pid, &oldAddr); - if (result == 2) - { - rVal->trace[rVal->traceLen].oldAddr = (uintptr_t) oldAddr; - rVal->trace[rVal->traceLen].size = 0; - rVal->trace[rVal->traceLen].addr = (uintptr_t) NULL; - - rVal->traceLen++; - continue; - } - - // malloc_init? - result = sscanf(buf, ":utrace: %u malloc_init()", - &pid); - if (result == 1) - { - continue; - } - - goto ERROR; - } - -RETURN: - return rVal; -ERROR: - fprintf(stderr, "mtrgraph: Error reading record %"PRIu64" of input\n", - rVal->traceLen + 1); - free(rVal->trace); - free(rVal); - rVal = NULL; - goto RETURN; -} - -bool -genOutput(FILE *outfile, const char *fileType, bool legend, - unsigned long xSize, unsigned long ySize, - Trace *trace, uint64_t minAddr, uint64_t maxAddr, uint64_t quantum, - uint64_t minEvent, uint64_t pastEvent, uint64_t stride) -{ - bool rVal; - gdImagePtr img; -#define NCOLORS 256 - int white, black; - int colors[NCOLORS]; - uint64_t i, buckets[ySize]; - unsigned long bucket; - unsigned long x = 0; - AllocationCache cache; - AllocationCacheRecord *rec, key; - gdFontPtr font; - - img = gdImageCreate((int) xSize, (int) ySize); - - black = gdImageColorAllocate(img, 0, 0, 0); - white = gdImageColorAllocate(img, 255, 255, 255); - // Create a palette of colors. - for (i = 0; i < NCOLORS; i++) - { - colors[i] = gdImageColorAllocate(img, 255 - i, i, - (i < NCOLORS / 2) ? i * 2 : (NCOLORS - i - 1) * 2); - } - - // Set up fonts. - font = gdFontGetLarge(); - - memset(buckets, 0, ySize * sizeof(uint64_t)); - - cache_tree_new(&cache); - - for (i = 0; i < trace->traceLen; i++) - { - if (trace->trace[i].oldAddr == 0 && trace->trace[i].addr != 0) - { - // malloc. - - // Update buckets. - if (trace->trace[i].size > 0) - { - uint64_t size, offset; - - size = trace->trace[i].size; - bucket = (trace->trace[i].addr - minAddr) / quantum; - offset = (trace->trace[i].addr - minAddr) % quantum; - - if (bucket < ySize) - { - if (quantum - offset >= size) - { - buckets[bucket] += size; - size = 0; - } - else - { - buckets[bucket] += (quantum - offset); - size -= (quantum - offset); - } - bucket++; - - while (bucket < ySize && size > 0) - { - if (size > quantum) - { - buckets[bucket] += quantum; - size -= quantum; - } - else - { - buckets[bucket] += size; - size = 0; - } - bucket++; - } - } - } - - // Cache size of allocation. - rec = (AllocationCacheRecord *) - malloc(sizeof(AllocationCacheRecord)); - if (rec == NULL) - { - fprintf(stderr, "mtrgraph: Error in malloc()\n"); - rVal = true; - goto RETURN; - } - - rec->addr = trace->trace[i].addr; - rec->size = trace->trace[i].size; - - cache_tree_insert(&cache, rec); - } - else if (trace->trace[i].oldAddr != 0 && trace->trace[i].addr != 0) - { - // realloc. - - // Remove old allocation from cache. - key.addr = trace->trace[i].oldAddr; - rec = cache_tree_search(&cache, &key); - if (rec == NULL) - { - fprintf(stderr, - "mtrgraph: Trace record %"PRIu64 - " realloc()s unknown object 0x%"PRIx64"\n", - i, (uint64_t)trace->trace[i].oldAddr); - rVal = true; - goto RETURN; - } - - // Update buckets (dealloc). - if (rec->size > 0) - { - uint64_t size, offset; - - size = rec->size; - bucket = (trace->trace[i].oldAddr - minAddr) / quantum; - offset = (trace->trace[i].oldAddr - minAddr) % quantum; - - if (bucket < ySize) - { - if (quantum - offset >= size) - { - buckets[bucket] -= size; - size = 0; - } - else - { - buckets[bucket] -= (quantum - offset); - size -= (quantum - offset); - } - bucket++; - - while (bucket < ySize && size > 0) - { - if (size > quantum) - { - buckets[bucket] -= quantum; - size -= quantum; - } - else - { - buckets[bucket] -= size; - size = 0; - } - bucket++; - } - } - } - - // Update buckets (alloc). - if (trace->trace[i].size > 0) - { - uint64_t size, offset; - - size = trace->trace[i].size; - bucket = (trace->trace[i].addr - minAddr) / quantum; - offset = (trace->trace[i].addr - minAddr) % quantum; - - if (bucket < ySize) - { - if (quantum - offset >= size) - { - buckets[bucket] += size; - size = 0; - } - else - { - buckets[bucket] += (quantum - offset); - size -= (quantum - offset); - } - bucket++; - - while (bucket < ySize && size > 0) - { - if (size > quantum) - { - buckets[bucket] += quantum; - size -= quantum; - } - else - { - buckets[bucket] += size; - size = 0; - } - bucket++; - } - } - } - - // Cache size of allocation. - cache_tree_remove(&cache, rec); - rec->addr = trace->trace[i].addr; - rec->size = trace->trace[i].size; - cache_tree_insert(&cache, rec); - } - else if (trace->trace[i].oldAddr != 0 - && trace->trace[i].size == 0 - && trace->trace[i].addr == 0) - { - // free. - - // Remove old allocation from cache. - key.addr = trace->trace[i].oldAddr; - rec = cache_tree_search(&cache, &key); - if (rec == NULL) - { - fprintf(stderr, - "mtrgraph: Trace record %"PRIu64 - " free()s unknown object 0x%"PRIx64"\n", - i, (uint64_t)trace->trace[i].oldAddr); - rVal = true; - goto RETURN; - } - - // Update buckets. - if (rec->size > 0) - { - uint64_t size, offset; - - size = rec->size; - bucket = (trace->trace[i].oldAddr - minAddr) / quantum; - offset = (trace->trace[i].oldAddr - minAddr) % quantum; - - if (bucket < ySize) - { - if (quantum - offset >= size) - { - buckets[bucket] -= size; - size = 0; - } - else - { - buckets[bucket] -= (quantum - offset); - size -= (quantum - offset); - } - bucket++; - - while (bucket < ySize && size > 0) - { - if (size > quantum) - { - buckets[bucket] -= quantum; - size -= quantum; - } - else - { - buckets[bucket] -= size; - size = 0; - } - bucket++; - } - } - } - - cache_tree_remove(&cache, rec); - free(rec); - } - - // Plot buckets in graph. - if (i >= minEvent && i < pastEvent && ((i - minEvent) % stride) == 0) - { - unsigned long j; - int color; - - for (j = 0; j < ySize; j++) - { - if (buckets[j] > 0) - { - color = (NCOLORS * ((double) buckets[j] / (double) quantum)) - - 1; - gdImageSetPixel(img, x, ySize - j, colors[color]); - } - } - x++; - } - } - - // Print graph legend. - if (legend) - { -#define BUFLEN 256 - char buf[BUFLEN]; - - // Create color palette legend. - if (ySize >= NCOLORS) - { - for (i = 0; i < NCOLORS; i++) - { - gdImageLine(img, 0, NCOLORS - i - 1, 31, NCOLORS - i - 1, - colors[i]); - } - gdImageLine(img, 0, 0, 31, 0, white); - gdImageLine(img, 0, 256, 31, 256, white); - gdImageLine(img, 0, 0, 0, 256, white); - gdImageLine(img, 31, 0, 31, 256, white); - - gdImageString(img, font, 40, 0, (unsigned char *)"Full bucket", - white); - gdImageString(img, font, 40, 240, - (unsigned char *)"Fragmented bucket", white); - } - - snprintf(buf, BUFLEN, - "Horizontal: Events [%"PRIu64"..%"PRIu64"), stride %"PRIu64"", - minEvent, pastEvent, stride); - gdImageString(img, font, 200, 0, (unsigned char *)buf, white); - - snprintf(buf, BUFLEN, - "Vertical: Addresses [0x%016"PRIx64"..0x%016"PRIx64 - "), bucket size %"PRIu64"", minAddr, maxAddr, quantum); - gdImageString(img, font, 200, 20, (unsigned char *)buf, white); - - snprintf(buf, BUFLEN, - "Graph dimensions: %lu events by %lu buckets", - xSize, ySize); - gdImageString(img, font, 200, 40, (unsigned char *)buf, white); - } - - if (strcmp(fileType, "png") == 0) - { - gdImagePng(img, outfile); - } - else if (strcmp(fileType, "jpg") == 0) - { - gdImageJpeg(img, outfile, 100); - } - else if (strcmp(fileType, "gif") == 0) - { - gdImageGif(img, outfile); - } - else - { - // Unreachable code. - fprintf(stderr, "mtrgraph: Unsupported output file type '%s'\n", - fileType); - rVal = true; - goto RETURN; - } - - rVal = false; -RETURN: - // Clean up cache. - while (true) - { - rec = cache_tree_first(&cache); - if (rec == NULL) - { - break; - } - - cache_tree_remove(&cache, rec); - free(rec); - } - gdImageDestroy(img); - return rVal; -} - -void -usage(FILE *fp) -{ - fprintf(fp, "mtrgraph usage:\n"); - fprintf(fp, " mtrgraph -h\n"); - fprintf(fp, " mtrgraph []\n"); - fprintf(fp, "\n"); - fprintf(fp, " Option | Description\n"); - fprintf(fp, " -----------+------------------------------------------\n"); - fprintf(fp, " -h | Print usage and exit.\n"); - fprintf(fp, " -n | Don't actually generate a graph.\n"); - fprintf(fp, " -q | Don't print statistics to stdout.\n"); - fprintf(fp, " -l | Don't generate legend in graph.\n"); - fprintf(fp, " -f | Input filename.\n"); - fprintf(fp, " -o | Output filename.\n"); - fprintf(fp, " -t | Output file type (png*, gif, jpg).\n"); - fprintf(fp, " -x | Horizontal size of graph area, in pixels.\n"); - fprintf(fp, " -y | Vertical size of graph area, in pixels.\n"); - fprintf(fp, " -m | Minimum address to graph.\n"); - fprintf(fp, " -M | Maximum address to graph.\n"); - fprintf(fp, " -e