[asterisk-commits] russell: branch russell/frame_caching r38571 - in
/team/russell/frame_caching...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sun Jul 30 23:45:32 MST 2006
Author: russell
Date: Mon Jul 31 01:45:31 2006
New Revision: 38571
URL: http://svn.digium.com/view/asterisk?rev=38571&view=rev
Log:
Implement a basic thread specific cache of dynamically allocated frame headers.
Added:
team/russell/frame_caching/include/asterisk/threadstorage.h
- copied unchanged from r38570, team/russell/ast_verbose_threadstorage/include/asterisk/threadstorage.h
Modified:
team/russell/frame_caching/frame.c
team/russell/frame_caching/include/asterisk/compiler.h
team/russell/frame_caching/include/asterisk/frame.h
team/russell/frame_caching/include/asterisk/utils.h
team/russell/frame_caching/utils.c
Modified: team/russell/frame_caching/frame.c
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/frame.c?rev=38571&r1=38570&r2=38571&view=diff
==============================================================================
--- team/russell/frame_caching/frame.c (original)
+++ team/russell/frame_caching/frame.c Mon Jul 31 01:45:31 2006
@@ -41,6 +41,8 @@
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
+#include "asterisk/threadstorage.h"
+#include "asterisk/linkedlists.h"
#ifdef TRACE_FRAMES
static int headers = 0;
@@ -56,6 +58,16 @@
static unsigned int mallocd_data = 0;
static unsigned int mallocd_src = 0;
static unsigned int mallocd_none = 0;
+
+static unsigned int added_to_cache = 0;
+static unsigned int removed_from_cache = 0;
+
+/*! \brief A per-thread cache of frame headers */
+AST_THREADSTORAGE(frame_cache, frame_cache_init);
+
+/*! \brief This is just so ast_frames, a list head struct for holding a list of
+ * ast_frame structures, is defined. */
+AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
#define SMOOTHER_SIZE 8000
@@ -261,26 +273,36 @@
static struct ast_frame *ast_frame_header_new(void)
{
- struct ast_frame *f = ast_calloc(1, sizeof(*f));
+ struct ast_frame *f;
+ struct ast_frames *frames;
+
+ if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
+ if ((f = AST_LIST_REMOVE_HEAD(frames, frame_list))) {
+ size_t old_len = f->mallocd_hdr_len;
+ memset(f, 0, sizeof(*f));
+ f->mallocd_hdr_len = old_len;
+ ast_atomic_fetchadd_int((int *) &removed_from_cache, 1);
+ return f;
+ }
+ }
+
+ if (!(f = ast_calloc(1, sizeof(*f))))
+ return NULL;
+
+ f->mallocd_hdr_len = sizeof(*f);
#ifdef TRACE_FRAMES
- if (f) {
- f->prev = NULL;
- ast_mutex_lock(&framelock);
- headers++;
- f->next = headerlist;
- if (headerlist)
- headerlist->prev = f;
- headerlist = f;
- ast_mutex_unlock(&framelock);
- }
+ ast_mutex_lock(&framelock);
+ headers++;
+ f->next = headerlist;
+ if (headerlist)
+ headerlist->prev = f;
+ headerlist = f;
+ ast_mutex_unlock(&framelock);
#endif
+
return f;
}
-/*!
- * \todo Important: I should be made more efficient. Frame headers should
- * most definitely be cached
- */
void ast_frfree(struct ast_frame *fr)
{
switch (fr->mallocd) {
@@ -310,6 +332,18 @@
break;
default:
ast_log(LOG_ERROR, "Totally bogus frame malloc'd value of '%d'!\n", fr->mallocd);
+ }
+
+ if (fr->mallocd == AST_MALLOCD_HDR) {
+ /* Cool, only the header is malloc'd, let's just cache those for now
+ * to keep things simple... */
+ struct ast_frames *frames;
+
+ if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
+ AST_LIST_INSERT_HEAD(frames, fr, frame_list);
+ ast_atomic_fetchadd_int((int *) &added_to_cache, 1);
+ return;
+ }
}
if (fr->mallocd & AST_MALLOCD_DATA) {
@@ -399,9 +433,10 @@
struct ast_frame *ast_frdup(const struct ast_frame *f)
{
+ struct ast_frames *frames;
struct ast_frame *out;
int len, srclen = 0;
- void *buf;
+ void *buf = NULL;
/* Start with standard stuff */
len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
/* If we have a source, add space for it */
@@ -413,16 +448,33 @@
srclen = strlen(f->src);
if (srclen > 0)
len += srclen + 1;
- if (!(buf = ast_calloc(1, len)))
- return NULL;
- out = buf;
- /* Set us as having malloc'd header only, so it will eventually
- get freed. */
+
+ if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(frames, out, frame_list) {
+ if (out->mallocd_hdr_len >= len) {
+ AST_LIST_REMOVE_CURRENT(frames, frame_list);
+ buf = out;
+ ast_atomic_fetchadd_int((int *) &removed_from_cache, 1);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ }
+
+ if (!buf) {
+ if (!(buf = ast_calloc(1, len)))
+ return NULL;
+ out = buf;
+ out->mallocd_hdr_len = len;
+ }
+
out->frametype = f->frametype;
out->subclass = f->subclass;
out->datalen = f->datalen;
out->samples = f->samples;
out->delivery = f->delivery;
+ /* Set us as having malloc'd header only, so it will eventually
+ get freed. */
out->mallocd = AST_MALLOCD_HDR;
out->offset = AST_FRIENDLY_OFFSET;
if (out->datalen) {
@@ -915,7 +967,7 @@
" Displays debugging statistics from framer\n";
#endif
-static int show_frfree_stats(int fd, int argc, char *argv[])
+static int show_framecache_stats(int fd, int argc, char *argv[])
{
if (argc != 3)
return RESULT_SHOWUSAGE;
@@ -929,16 +981,22 @@
"header: %d\n"
"data: %d\n"
"src: %d\n"
- "none: %d\n",
+ "none: %d\n\n",
mallocd_header_data_src, mallocd_header_data, mallocd_header_src,
mallocd_data_src, mallocd_header, mallocd_data, mallocd_src, mallocd_none);
+
+ ast_cli(fd, "Frame cache statistics\n"
+ "------------------------------------------------------------\n"
+ "Added to cache: %d\n"
+ "Removed from cache: %d\n",
+ added_to_cache, removed_from_cache);
return RESULT_SUCCESS;
}
-static char frfree_stats_usage[] =
-"Usage: show frfree stats\n"
-" Display information about malloc'd frame elements passed to ast_frfree\n";
+static char framecache_stats_usage[] =
+"Usage: show framecache stats\n"
+" Display statistics related to the frame header cache.\n";
/* Builtin Asterisk CLI-commands for debugging */
static struct ast_cli_entry my_clis[] = {
@@ -950,7 +1008,7 @@
#ifdef TRACE_FRAMES
{ { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
#endif
-{ { "show", "frfree", "stats", NULL }, show_frfree_stats, "Show ast_frfree stats", frfree_stats_usage },
+{ { "show", "framecache", "stats", NULL }, show_framecache_stats, "Show ast_framecache stats", framecache_stats_usage },
};
int init_framer(void)
Modified: team/russell/frame_caching/include/asterisk/compiler.h
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/include/asterisk/compiler.h?rev=38571&r1=38570&r2=38571&view=diff
==============================================================================
--- team/russell/frame_caching/include/asterisk/compiler.h (original)
+++ team/russell/frame_caching/include/asterisk/compiler.h Mon Jul 31 01:45:31 2006
@@ -33,5 +33,6 @@
#endif
#define attribute_const __attribute__((const))
+#define attribute_unused __attribute__((unused))
#endif /* _ASTERISK_COMPILER_H */
Modified: team/russell/frame_caching/include/asterisk/frame.h
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/include/asterisk/frame.h?rev=38571&r1=38570&r2=38571&view=diff
==============================================================================
--- team/russell/frame_caching/include/asterisk/frame.h (original)
+++ team/russell/frame_caching/include/asterisk/frame.h Mon Jul 31 01:45:31 2006
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include "asterisk/endian.h"
+#include "asterisk/linkedlists.h"
struct ast_codec_pref {
char order[32];
@@ -97,6 +98,8 @@
int samples;
/*! Was the data malloc'd? i.e. should we free it when we discard the frame? */
int mallocd;
+ /*! The number of bytes allocated for a malloc'd frame header */
+ size_t mallocd_hdr_len;
/*! How many bytes exist _before_ "data" that can be used if needed */
int offset;
/*! Optional source of frame for debugging */
@@ -109,6 +112,8 @@
struct ast_frame *prev;
/*! Next/Prev for linking stand alone frames */
struct ast_frame *next;
+ /*! XXX This should replace the next/prev pointers XXX */
+ AST_LIST_ENTRY(ast_frame) frame_list;
/*! Timing data flag */
int has_timing_info;
/*! Timestamp in milliseconds */
Modified: team/russell/frame_caching/include/asterisk/utils.h
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/include/asterisk/utils.h?rev=38571&r1=38570&r2=38571&view=diff
==============================================================================
--- team/russell/frame_caching/include/asterisk/utils.h (original)
+++ team/russell/frame_caching/include/asterisk/utils.h Mon Jul 31 01:45:31 2006
@@ -35,6 +35,7 @@
#include "asterisk/time.h"
#include "asterisk/strings.h"
#include "asterisk/logger.h"
+#include "asterisk/compiler.h"
/*! \note
\verbatim
@@ -272,6 +273,22 @@
long int ast_random(void);
#endif
+/*!
+ * \brief free() wrapper
+ *
+ * ast_free should be used when a function pointer for free() needs to be passed
+ * as the argument to an application. Otherwise, astmm will cause seg faults.
+ */
+#ifdef __AST_DEBUG_MALLOC
+static void ast_free(void *ptr) attribute_unused;
+static void ast_free(void *ptr)
+{
+ free(ptr);
+}
+#else
+#define ast_free free
+#endif
+
#ifndef __AST_DEBUG_MALLOC
/*!
Modified: team/russell/frame_caching/utils.c
URL: http://svn.digium.com/view/asterisk/team/russell/frame_caching/utils.c?rev=38571&r1=38570&r2=38571&view=diff
==============================================================================
--- team/russell/frame_caching/utils.c (original)
+++ team/russell/frame_caching/utils.c Mon Jul 31 01:45:31 2006
@@ -58,6 +58,9 @@
#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
#include "asterisk/utils.h"
+
+#define AST_API_MODULE
+#include "asterisk/threadstorage.h"
static char base64[64];
static char b2a[256];
More information about the asterisk-commits
mailing list