[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