]>
jfr.im git - irc/quakenet/newserv.git/blob - nsmstats/nsmstats.c
6 #include "../core/nsmalloc.h"
7 #include "../core/hooks.h"
8 #include "../control/control.h"
10 void nsmstats(int hookhum
, void *arg
);
11 int nsmhistogram(void *sender
, int cargc
, char **cargv
);
14 registerhook(HOOK_CORE_STATSREQUEST
, &nsmstats
);
15 registercontrolhelpcmd("nsmhistogram", NO_DEVELOPER
,1,&nsmhistogram
,"Usage: nsmhistogram [pool id]\nDisplays memory information for given pool.");
19 deregisterhook(HOOK_CORE_STATSREQUEST
, &nsmstats
);
20 deregistercontrolcmd("nsmhistogram", &nsmhistogram
);
23 static char *formatmbuf(unsigned long count
, size_t size
, size_t realsize
) {
24 static char buf
[1024];
26 snprintf(buf
, sizeof(buf
), "%lu items, %luKb allocated for %luKb, %luKb (%.2f%%) overhead", count
, (unsigned long)size
/ 1024, (unsigned long)realsize
/ 1024, (unsigned long)(realsize
- size
) / 1024, (double)(realsize
- size
) / (double)size
* 100);
30 void nsmgenstats(struct nsmpool
*pool
, double *mean
, double *stddev
) {
31 unsigned long long int sumsq
= 0;
34 *mean
= (double)pool
->size
/ pool
->count
;
36 for (np
=pool
->first
.next
;np
;np
=np
->next
)
37 sumsq
+=np
->size
* np
->size
;
39 *stddev
= sqrtf((double)sumsq
/ pool
->count
- *mean
* *mean
);
42 void nsmstats(int hookhum
, void *arg
) {
44 char buf
[1024], extra
[1024];
45 unsigned long totalcount
= 0;
46 size_t totalsize
= 0, totalrealsize
= 0;
47 long level
= (long)arg
;
49 for (i
=0;i
<MAXPOOL
;i
++) {
50 struct nsmpool
*pool
=&nsmpools
[i
];
56 realsize
=pool
->size
+ pool
->count
* sizeof(struct nsminfo
) + sizeof(struct nsmpool
);
58 totalsize
+=pool
->size
;
59 totalrealsize
+=realsize
;
60 totalcount
+=pool
->count
;
66 nsmgenstats(pool
, &mean
, &stddev
);
68 snprintf(extra
, sizeof(extra
), ", mean: %.2fKb stddev: %.2fKb", mean
/ 1024, stddev
/ 1024);
71 snprintf(buf
, sizeof(buf
), "NSMalloc: pool %2d (%10s): %s%s", i
, nsmpoolnames
[i
]?nsmpoolnames
[i
]:"??", formatmbuf(pool
->count
, pool
->size
, realsize
), extra
);
72 triggerhook(HOOK_CORE_STATSREPLY
, buf
);
76 snprintf(buf
, sizeof(buf
), "NSMalloc: pool totals: %s", formatmbuf(totalcount
, totalsize
, totalrealsize
));
77 triggerhook(HOOK_CORE_STATSREPLY
, buf
);
80 struct nsmhistogram_s
{
85 static int hcompare_size(const void *a
, const void *b
) {
86 return ((struct nsmhistogram_s
*)a
)->size
- ((struct nsmhistogram_s
*)b
)->size
;
89 static int hcompare_freq(const void *a
, const void *b
) {
90 return ((struct nsmhistogram_s
*)a
)->freq
- ((struct nsmhistogram_s
*)b
)->freq
;
94 * since this is gonna process over a million allocations, we can't just do
95 * it the simple O(n^2) way, so here's the crazy fast(er) way:
96 * we create a list of all sizes and sort them, then store unique items
97 * we can then calculate frequencies in O(n log n) time by searching this
98 * sorted list using a binary chop...
100 int nsmhistogram(void *sender
, int cargc
, char **cargv
) {
103 struct nsmpool
*pool
;
105 struct nsmhistogram_s
*freqs
;
112 poolid
= atoi(cargv
[0]);
113 if(poolid
> MAXPOOL
) {
114 controlreply(sender
, "Bad pool id.");
118 pool
= &nsmpools
[poolid
];
119 if(pool
->count
== 0) {
120 controlreply(sender
, "Pool is empty.");
124 freqs
= (struct nsmhistogram_s
*)malloc(sizeof(struct nsmhistogram_s
) * pool
->count
);
126 controlreply(sender
, "Error allocating first BIG array.");
131 memset(freqs
, 0, sizeof(struct nsmhistogram_s
) * pool
->count
);
132 for(i
=0,np
=pool
->first
.next
;np
;np
=np
->next
)
133 freqs
[i
++].size
= np
->size
;
136 qsort(freqs
, pool
->count
, sizeof(struct nsmhistogram_s
), hcompare_size
);
139 cval
= freqs
[0].size
;
141 for(i
=1;i
<pool
->count
;i
++) {
142 if(cval
!= freqs
[i
].size
) {
143 cval
= freqs
[i
].size
;
144 freqs
[dst
++].size
= freqs
[i
].size
;
148 /* outer loop is O(n), inner loop is O(1 + log n) => O(n + n log n) => O(n log n) */
149 for(np
=pool
->first
.next
;np
;np
=np
->next
) {
150 unsigned long low
= 0, high
= dst
;
152 unsigned long mid
= (low
+ high
) / 2;
153 if (freqs
[mid
].size
< np
->size
) {
159 if((low
> np
->size
) || (freqs
[low
].size
!= np
->size
)) {
160 controlreply(sender
, "ERROR");
168 qsort(freqs
, dst
, sizeof(struct nsmhistogram_s
), hcompare_freq
);
171 for(i
=dst
-1;i
>=0&&max
-->0;i
--)
172 controlreply(sender
, "%10lu: %10lu", (unsigned long)freqs
[i
].size
, (unsigned long)freqs
[i
].freq
);