]>
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"
9 #include "../lib/version.h"
13 void nsmstats(int hookhum
, void *arg
);
14 int nsmhistogram(void *sender
, int cargc
, char **cargv
);
17 registerhook(HOOK_CORE_STATSREQUEST
, &nsmstats
);
18 registercontrolhelpcmd("nsmhistogram", NO_DEVELOPER
,1,&nsmhistogram
,"Usage: nsmhistogram [pool id]\nDisplays memory information for given pool.");
22 deregisterhook(HOOK_CORE_STATSREQUEST
, &nsmstats
);
23 deregistercontrolcmd("nsmhistogram", &nsmhistogram
);
26 static char *formatmbuf(unsigned long count
, size_t size
, size_t realsize
) {
27 static char buf
[1024];
29 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);
33 void nsmgenstats(struct nsmpool
*pool
, double *mean
, double *stddev
) {
34 unsigned long long int sumsq
= 0;
37 *mean
= (double)pool
->size
/ pool
->count
;
39 for (np
=pool
->first
.next
;np
;np
=np
->next
)
40 sumsq
+=np
->size
* np
->size
;
42 *stddev
= sqrtf((double)sumsq
/ pool
->count
- *mean
* *mean
);
45 void nsmstats(int hookhum
, void *arg
) {
47 char buf
[1024], extra
[1024];
48 unsigned long totalcount
= 0;
49 size_t totalsize
= 0, totalrealsize
= 0;
50 long level
= (long)arg
;
52 for (i
=0;i
<MAXPOOL
;i
++) {
53 struct nsmpool
*pool
=&nsmpools
[i
];
59 realsize
=pool
->size
+ pool
->count
* sizeof(struct nsminfo
) + sizeof(struct nsmpool
);
61 totalsize
+=pool
->size
;
62 totalrealsize
+=realsize
;
63 totalcount
+=pool
->count
;
69 nsmgenstats(pool
, &mean
, &stddev
);
71 snprintf(extra
, sizeof(extra
), ", mean: %.2fKb stddev: %.2fKb", mean
/ 1024, stddev
/ 1024);
74 snprintf(buf
, sizeof(buf
), "NSMalloc: pool %2d (%10s): %s%s", i
, nsmpoolnames
[i
]?nsmpoolnames
[i
]:"??", formatmbuf(pool
->count
, pool
->size
, realsize
), extra
);
75 triggerhook(HOOK_CORE_STATSREPLY
, buf
);
79 snprintf(buf
, sizeof(buf
), "NSMalloc: pool totals: %s", formatmbuf(totalcount
, totalsize
, totalrealsize
));
80 triggerhook(HOOK_CORE_STATSREPLY
, buf
);
83 struct nsmhistogram_s
{
88 static int hcompare_size(const void *a
, const void *b
) {
89 return ((struct nsmhistogram_s
*)a
)->size
- ((struct nsmhistogram_s
*)b
)->size
;
92 static int hcompare_freq(const void *a
, const void *b
) {
93 return ((struct nsmhistogram_s
*)a
)->freq
- ((struct nsmhistogram_s
*)b
)->freq
;
97 * since this is gonna process over a million allocations, we can't just do
98 * it the simple O(n^2) way, so here's the crazy fast(er) way:
99 * we create a list of all sizes and sort them, then store unique items
100 * we can then calculate frequencies in O(n log n) time by searching this
101 * sorted list using a binary chop...
103 int nsmhistogram(void *sender
, int cargc
, char **cargv
) {
106 struct nsmpool
*pool
;
108 struct nsmhistogram_s
*freqs
;
115 poolid
= atoi(cargv
[0]);
116 if(poolid
> MAXPOOL
) {
117 controlreply(sender
, "Bad pool id.");
121 pool
= &nsmpools
[poolid
];
122 if(pool
->count
== 0) {
123 controlreply(sender
, "Pool is empty.");
127 freqs
= (struct nsmhistogram_s
*)malloc(sizeof(struct nsmhistogram_s
) * pool
->count
);
129 controlreply(sender
, "Error allocating first BIG array.");
134 memset(freqs
, 0, sizeof(struct nsmhistogram_s
) * pool
->count
);
135 for(i
=0,np
=pool
->first
.next
;np
;np
=np
->next
)
136 freqs
[i
++].size
= np
->size
;
139 qsort(freqs
, pool
->count
, sizeof(struct nsmhistogram_s
), hcompare_size
);
142 cval
= freqs
[0].size
;
144 for(i
=1;i
<pool
->count
;i
++) {
145 if(cval
!= freqs
[i
].size
) {
146 cval
= freqs
[i
].size
;
147 freqs
[dst
++].size
= freqs
[i
].size
;
151 /* outer loop is O(n), inner loop is O(1 + log n) => O(n + n log n) => O(n log n) */
152 for(np
=pool
->first
.next
;np
;np
=np
->next
) {
153 unsigned long low
= 0, high
= dst
;
155 unsigned long mid
= (low
+ high
) / 2;
156 if (freqs
[mid
].size
< np
->size
) {
162 if((low
> np
->size
) || (freqs
[low
].size
!= np
->size
)) {
163 controlreply(sender
, "ERROR");
171 qsort(freqs
, dst
, sizeof(struct nsmhistogram_s
), hcompare_freq
);
174 for(i
=dst
-1;i
>=0&&max
-->0;i
--)
175 controlreply(sender
, "%10lu: %10lu", (unsigned long)freqs
[i
].size
, (unsigned long)freqs
[i
].freq
);