📄 malloc_rec.c
字号:
/******************************************************************************* ** Copyright 2005 University of Cambridge Computer Laboratory. ** ** This file is part of Nprobe. ** ** Nprobe is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** Nprobe is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Nprobe; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** *******************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <assert.h>#include <sys/time.h>#include <sys/resource.h>#include <unistd.h>#include "list.h"#include "malloc_rec.h"#ifdef REC_MALLOC#define NBKTS 16*16384#define HASHMOD 16381#undef malloc#undef freestruct mrec{ list_t hlist; void *addr; int size; int gen;#ifdef REC_MALLOC_MED char *what;#endif};typedef struct mrec mrec_t;static listhdr_t mrec_pool;static listhdr_t mrecs[NBKTS];#define NWBKTS 1024#define WHASHMOD 1021struct whatrec { list_t hlist; char *what;};typedef struct whatrec whatrec_t;static listhdr_t whatrecs[NWBKTS];static void init_whatrecs(void){ int i; for (i = 0; i < NWBKTS; i++) L_INIT(&whatrecs[i]); }static int hashwhat(char *what){ int l = strlen(what); int ind; while( l > sizeof(int)) { ind ^= *((int *)what); what += sizeof(int); l -= sizeof(int); } while (l) { ind ^= (int)*what; l -= 1; what += 1; } return ind % WHASHMOD;} static char *getwhat(char* what){ whatrec_t *wp; char *nwhat; listhdr_t *bkt = &whatrecs[hashwhat(what)]; int found = 0; L_WALK(wp, bkt, hlist, whatrec_t) { if (!strcmp(what, wp->what)) { found = 1; break; } } if (!found) { if ((wp = (whatrec_t *)malloc(sizeof(whatrec_t))) ==NULL) { perror("whatrec malloc()"); exit(1); } if ((nwhat = (char *)malloc(strlen(what))) ==NULL) { perror("whatrec char malloc()"); exit(1); } strcpy(nwhat, what); wp->what = nwhat; } return wp->what;} static int started = 0;static int nmallocs = 0;static int nfrees = 0;static int mused = 0;void report_rec_malloc_full(void); /* forward */static void mrec_pool_init(int n, int init){ int i; mrec_t *mrp; if (init) fprintf(stderr, "initialising %d mrecs ", n); if ((mrp = (mrec_t *)malloc(n * sizeof(mrec_t))) == NULL) perror("mrec_pool_init"); L_INIT(&mrec_pool); for (i = 0; i < n; i++) { L_INS_TAIL(&mrec_pool, &mrp[i], hlist, mrec_t); if (init && !(i%(n/20))) fprintf(stderr, "."); } if (init) fprintf(stderr, "\n"); return;}static mrec_t *get_mrec(void){ mrec_t *mrp; if (L_EMPTY(&mrec_pool)) { //fprintf(stderr, "Initialising another %d mrecs in pool\n", NBKTS/2); mrec_pool_init(NBKTS/2, 0); } mrp = (mrec_t *)mrec_pool.lnext; L_REM(&mrec_pool, mrp, hlist, mrec_t); mrp->gen = 0; return mrp;}static void recycle_mrec(mrec_t *mrp){ L_INS_HEAD(&mrec_pool, mrp, hlist, mrec_t); return;}static void hash_init(void){ int i; started = 1; for (i=0; i <NBKTS; i++) L_INIT(&mrecs[i]); mrec_pool_init(2*NBKTS, 1);#ifdef REC_MALLOC_MED init_whatrecs();#endif return;}#ifdef REC_MALLOC_MEDvoid *_rec_malloc(size_t sz, char *what)#elif defined REC_MALLOC_MAXvoid *_rec_malloc(size_t sz, char *what, int line, char *file)#elsevoid *_rec_malloc(size_t sz)#endif{ list_t *bkt; mrec_t *mrecp; void *ad;#ifdef REC_MALLOC_MED //printf("%s = %d\n", what, sz);#elif defined REC_MALLOC_MAX printf("%s = %d %s:%d\n", what, sz, file, line); //#else // printf("rec_malloc called\n");#endif if (!started) hash_init(); nmallocs += 1; mused += sz; ad = malloc(sz); if (ad == NULL) return NULL; mrecp = get_mrec(); mrecp->addr = ad; mrecp->size = sz;#ifdef REC_MALLOC_MED mrecp->what = getwhat(what);#endif bkt = &mrecs[(int)ad%HASHMOD]; L_INS_TAIL(bkt, mrecp, hlist, mrec_t); return ad;}void _rec_free(void *addr){ int found = 0; list_t *bkt; mrec_t *mrecp; if (!started) { fprintf(stderr, "_rec_free(): freeing address %#x before first allocated\n", (int)addr); exit(1); } //if (!(nfrees%100000)) //report_rec_malloc_full(); //fprintf (stderr, "_rec_free %#x\n", (int)addr); bkt = &mrecs[(int)addr%HASHMOD]; L_WALK(mrecp, bkt, hlist, mrec_t) { if (mrecp->addr == addr) { found = 1; break; } } if (!found) { fprintf(stderr, "_rec_free(): freeing address %#x before allocated\n", (int)addr); exit(1); } else { free(addr); nfrees += 1; mused -= mrecp->size; L_REM(bkt, mrecp, hlist, mrec_t); recycle_mrec(mrecp); } return; }void report_rec_malloc(void){ fprintf(stderr, "%d mallocs %d frees %d used\n\n", nmallocs, nfrees, mused);}#define NSB 2048#define NSBMOD 2039struct msize_rec { list_t hlist; int size; int num; int gen;#ifdef REC_MALLOC_MED char *what;#endif};typedef struct msize_rec ms_t;int sortfn(const void *aa, const void *bb){ ms_t **ap = aa; ms_t **bp = bb; ms_t *a = *ap; ms_t *b = *bp; return (b->num*b->size) - (a->num*a->size);}void report_rec_malloc_full(void){ int i, j; int found; int gen; list_t *bkt, *sbkt; mrec_t *mrecp; ms_t *mstp, **mstpp; int sz; int nsizes; listhdr_t sizes[NSB]; int szrep = 0; struct rusage ru; for (i=0; i <NSB; i++) L_INIT(&sizes[i]); nsizes = 0; for (i=0; i <NBKTS; i++) { bkt = &mrecs[i]; L_WALK(mrecp, bkt, hlist, mrec_t) { sz = mrecp->size; gen = mrecp->gen; mrecp->gen += 1; sbkt = &sizes[sz%NSBMOD]; found = 0; L_WALK(mstp, sbkt, hlist, ms_t) {#ifdef REC_MALLOC_MED if(mstp->size == sz && mstp->gen == gen && !strcmp(mstp->what, mrecp->what))#else if(mstp->size == sz && mstp->gen == gen)#endif { found = 1; break; } } if (found) { mstp->num += 1; } else { if ((mstp = (ms_t *)malloc(sizeof(ms_t))) == NULL) { perror("report_rec_malloc_full: malloc"); exit(1); } mstp->size = sz; mstp->gen = gen; mstp->num = 1;#ifdef REC_MALLOC_MED mstp->what = mrecp->what;#endif L_INS_TAIL(sbkt, mstp, hlist, ms_t); nsizes += 1; } } } if ((mstpp = (ms_t **)malloc(nsizes*sizeof(ms_t *))) == NULL) { perror("report_rec_malloc_full: malloc2"); exit(1); } j = 0; for (i=0; i <NSB; i++) { sbkt = &sizes[i]; L_WALK(mstp, sbkt, hlist, ms_t) if (mstp->num) mstpp[j++] = mstp; } qsort(mstpp, nsizes, sizeof(ms_t *), sortfn); fprintf(stderr, "%d mallocs %d frees %.2fM total used\n", nmallocs, nfrees, mused/1000000.0); fprintf(stderr, "Top 75+%%:\n"); for (i = 0; i < nsizes; i++) { ms_t *msp = mstpp[i]; szrep += msp->num * msp->size;#ifdef REC_MALLOC_MED fprintf(stderr, "\t%d of size %d = %.2fM gen=%d %s running tot %.2fM\n", msp->num, msp->size, (msp->num * msp->size)/1000000.0, msp->gen, msp->what, szrep/1000000.0);#else fprintf(stderr, "\t%d of size %d = %.2fM gen %d running tot %.2fM\n", msp->num, msp->size, (msp->num * msp->size)/1000000.0, msp->gen, szrep/1000000.0);#endif if (szrep > (mused*3)/4) break; } for (i = 0; i < nsizes; i++) free(mstpp[i]); free(mstpp); if (getrusage(RUSAGE_SELF, &ru) != 0) { perror("malloc_rec: rusage()"); exit(1); }#if 0 fprintf(stderr, "mrss %d shm %d unshm %d st %d\n", ru.ru_maxrss, ru.ru_ixrss, ru.ru_idrss, ru.ru_isrss);#endif }#else /* ifdef REC_MALLOC */void report_rec_malloc_full(void){ return;}#endif /* ifdef REC_MALLOC *//* * end malloc_trace.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -