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.
This commit is contained in:
Jason Evans 2010-02-11 13:38:12 -08:00
parent d34f9e7e93
commit fe5faa2cc5
17 changed files with 13 additions and 1885 deletions

View File

@ -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)

View File

@ -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}])

View File

@ -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.<pid>.<arena>
@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 ,

View File

@ -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

View File

@ -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"

View File

@ -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 */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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);
}

View File

@ -2023,49 +2023,6 @@ arena_new(arena_t *arena, unsigned ind)
# endif
#endif
#ifdef JEMALLOC_TRACE
if (opt_trace) {
/* "jemtr.<pid>.<arena>" */
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("<jemalloc>",
": creat(\"", filename, "\", 0644) failed\n");
abort();
}
}
#endif
#ifdef JEMALLOC_PROF
arena->prof_accumbytes = 0;
#endif

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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("<jemalloc>",
": 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("<jemalloc>", ": Error in atexit()\n", "", "");
if (opt_abort)
abort();
}
/* Receive thread exit notifications. */
if (pthread_key_create(&trace_tsd, trace_thread_cleanup) != 0) {
malloc_write4("<jemalloc>",
": Error in pthread_key_create()\n", "", "");
abort();
}
return (false);
}
/******************************************************************************/
#endif /* JEMALLOC_TRACE */

View File

@ -1,12 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,225 +0,0 @@
// Parse a malloc trace and simulate the allocation events. Records look like:
//
// <jemalloc>:utrace: 31532 malloc_init()
// <jemalloc>:utrace: 31532 0x800b01000 = malloc(34816)
// <jemalloc>:utrace: 31532 free(0x800b0a400)
// <jemalloc>:utrace: 31532 0x800b35230 = realloc(0x800b35230, 45)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "internal/mtrplay_defs.h"
#ifndef JEMALLOC_DEBUG
# define NDEBUG
#endif
#include <assert.h>
#include "internal/rb.h"
typedef struct record_s record_t;
struct record_s {
rb_node(record_t) link;
uintptr_t tag;
void *obj;
};
typedef rb_tree(record_t) record_tree_t;
static int
record_comp(record_t *a, record_t *b)
{
if (a->tag < b->tag)
return (-1);
else if (a->tag == b->tag)
return (0);
else
return (1);
}
rb_wrap(static JEMALLOC_ATTR(unused), record_tree_, record_tree_t, record_t,
link, record_comp)
static record_t *rec_stack = NULL;
static record_t *
record_alloc(void)
{
record_t *ret;
if (rec_stack == NULL) {
record_t *recs;
unsigned long i;
#define MMAP_SIZE (1024 * 1024 * 1024)
recs = (record_t *)mmap(NULL, MMAP_SIZE,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (recs == NULL) {
fprintf(stderr, "mtrplay: mmap() error (OOM)\n");
exit(1);
}
for (i = 0; i < MMAP_SIZE / sizeof(record_t); i++) {
recs[i].obj = (void *)rec_stack;
rec_stack = &recs[i];
}
}
ret = rec_stack;
rec_stack = (record_t *)ret->obj;
return (ret);
}
static void
record_dalloc(record_t *rec)
{
rec->obj = (void *)rec_stack;
rec_stack = rec;
}
int
main(void)
{
uint64_t line;
int result;
char fbuf[4096], lbuf[128];
unsigned foff, flen, i;
unsigned pid;
void *addr, *oldaddr;
size_t size;
record_tree_t tree;
record_tree_new(&tree);
foff = flen = 0;
for (line = 1;; line++) {
if (line % 100000 == 0)
fprintf(stderr, ".");
// Get a line of input.
for (i = 0; i < sizeof(lbuf) - 1; i++) {
// Refill the read buffer if necessary. We use read(2)
// instead of a higher level API in order to avoid
// internal allocation.
if (foff == flen) {
foff = 0;
flen = read(0, fbuf, sizeof(fbuf));
if (flen <= 0) {
goto RETURN;
}
}
switch (fbuf[foff]) {
case '\n': {
lbuf[i] = '\0';
foff++;
goto OUT;
} default: {
lbuf[i] = fbuf[foff];
foff++;
break;
}
}
}
OUT:;
// realloc?
result = sscanf(lbuf,
"<jemalloc>:utrace: %u %p = realloc(%p, %zu)",
&pid, &addr, &oldaddr, &size);
if (result == 4) {
record_t key, *rec;
void *p;
key.tag = (uintptr_t)oldaddr;
rec = record_tree_search(&tree, &key);
if (rec == NULL) {
fprintf(stderr,
"mtrplay: Line %"PRIu64
": Record not found\n", line);
exit(1);
}
record_tree_remove(&tree, rec);
p = realloc(rec->obj, size);
if (p == NULL) {
fprintf(stderr, "mtrplay: Line %"PRIu64
": OOM\n", line);
exit(1);
}
rec->tag = (uintptr_t)addr;
rec->obj = p;
record_tree_insert(&tree, rec);
continue;
}
// malloc?
result = sscanf(lbuf, "<jemalloc>:utrace: %u %p = malloc(%zu)",
&pid, &addr, &size);
if (result == 3)
{
void *p;
record_t *rec;
rec = record_alloc();
p = malloc(size);
if (p == NULL) {
fprintf(stderr, "mtrplay: Line %"PRIu64
": OOM\n", line);
exit(1);
}
memset(p, 0, size);
rec->tag = (uintptr_t)addr;
rec->obj = p;
record_tree_insert(&tree, rec);
continue;
}
// free?
result = sscanf(lbuf, "<jemalloc>:utrace: %u free(%p)",
&pid, &oldaddr);
if (result == 2)
{
record_t key, *rec;
key.tag = (uintptr_t)oldaddr;
rec = record_tree_search(&tree, &key);
if (rec == NULL) {
fprintf(stderr,
"mtrplay: Line %"PRIu64
": Record not found\n", line);
exit(1);
}
record_tree_remove(&tree, rec);
free(rec->obj);
record_dalloc(rec);
continue;
}
// malloc_init?
result = sscanf(lbuf, "<jemalloc>:utrace: %u malloc_init()",
&pid);
if (result == 1)
{
continue;
}
fprintf(stderr, "mtrplay: Error reading line %"PRIu64
" of input\n", line);
exit(1);
}
RETURN:
return 0;
}