2 * Copyright (c) 2008 - Secure Endpoints Inc.
17 static cm_fid_stats_t ** fidStatsHashTablep = NULL;
18 static afs_uint32 fidStatsHashTableSize = 0;
21 * algorithm and implementation adapted from code written by
22 * Frank Pilhofer <fp@fpx.de>
24 afs_uint32 nearest_prime(afs_uint32 s)
26 #define TEST(f,x) (*(f+(x)/16)&(1<<(((x)%16L)/2)))
27 #define SET(f,x) *(f+(x)/16)|=1<<(((x)%16L)/2)
28 unsigned char *feld=NULL, *zzz;
29 afs_uint32 teste=1, mom, hits=1, count, max, alloc, largest_prime = 0;
34 zzz = feld = malloc (alloc=((max>>4)+1L));
36 for (count=0; count<alloc; count++)
39 while ((teste+=2) < max) {
40 if (!TEST(feld, teste)) {
41 for (mom=3L*teste; mom<max; mom+=teste<<1)
49 while ((count+=2)<max) {
50 if (!TEST(feld,count)) {
51 largest_prime = count;
59 /* We never free these objects so we don't need to
60 * worry about reuse or tracking the allocations
62 * The management of the free allocation is not
63 * thread safe because we never expect this code
64 * to be called from more than one thread.
66 cm_fid_stats_t * cm_PerformanceGetNew(void)
68 static cm_fid_stats_t * allocp = NULL;
69 static afs_int32 allocSize = 0;
70 static afs_int32 nextFree = 0;
72 if (nextFree < allocSize)
73 return &allocp[nextFree++];
75 allocp = (cm_fid_stats_t *)malloc(32768);
79 allocSize = 32768/sizeof(cm_fid_stats_t);
80 memset(allocp, 0, 32768);
85 void cm_PerformanceInsertToHashTable(cm_fid_stats_t *statp)
87 afs_uint32 hash = statp->fid.hash % fidStatsHashTableSize;
89 statp->nextp = fidStatsHashTablep[hash];
90 fidStatsHashTablep[hash] = statp;
93 void cm_PerformanceAddSCache(cm_scache_t *scp)
95 cm_fid_stats_t * statp = cm_PerformanceGetNew();
100 lock_ObtainRead(&scp->rw);
101 if (!(scp->flags & CM_SCACHEFLAG_DELETED)) {
102 statp->fid = scp->fid;
103 statp->fileLength = scp->length;
104 statp->fileType = scp->fileType;
105 statp->flags = CM_FIDSTATS_FLAG_HAVE_SCACHE;
106 lock_ConvertRToW(&scp->rw);
107 if (cm_HaveCallback(scp))
108 statp->flags |= CM_FIDSTATS_FLAG_CALLBACK;
109 lock_ConvertWToR(&scp->rw);
110 if (scp->flags & CM_SCACHEFLAG_RO)
111 statp->flags |= CM_FIDSTATS_FLAG_RO;
112 if (scp->flags & CM_SCACHEFLAG_PURERO)
113 statp->flags |= CM_FIDSTATS_FLAG_PURERO;
115 lock_ReleaseRead(&scp->rw);
118 if (statp->fid.vnode == 1) {
119 cm_volume_t *volp = NULL;
120 cm_cell_t *cellp = NULL;
125 cellp = cm_FindCellByID(statp->fid.cell, 0);
127 if (!cm_FindVolumeByID(cellp, statp->fid.volume, cm_rootUserp, &req, 0, &volp)) {
128 statp->flags |= CM_FIDSTATS_HAVE_VOLUME;
135 cm_PerformanceInsertToHashTable(statp);
139 void cm_PerformanceTuningInit(void)
147 cm_fid_stats_t * statp;
149 fidStatsHashTableSize = nearest_prime(cm_data.stats/3);
150 if (fidStatsHashTableSize == 0)
151 fidStatsHashTableSize = cm_data.stats/3;
152 fidStatsHashTablep = (cm_fid_stats_t **)malloc(fidStatsHashTableSize * sizeof(cm_fid_stats_t *));
153 if (fidStatsHashTablep == NULL) {
154 fidStatsHashTableSize = 0;
158 memset(fidStatsHashTablep, 0, fidStatsHashTableSize * sizeof(cm_fid_stats_t *));
160 lock_ObtainRead(&cm_scacheLock);
161 for (i=0; i<cm_data.scacheHashTableSize; i++) {
162 for (scp=cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
163 if (scp->fid.cell == 0)
165 lock_ReleaseRead(&cm_scacheLock);
166 cm_PerformanceAddSCache(scp);
167 lock_ObtainRead(&cm_scacheLock);
170 lock_ReleaseRead(&cm_scacheLock);
172 lock_ObtainRead(&cm_volumeLock);
173 for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
174 if (volp->vol[RWVOL].ID) {
175 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
176 hash = fid.hash % fidStatsHashTableSize;
178 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
179 if (!cm_FidCmp(&fid, &statp->fid)) {
180 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
185 statp = cm_PerformanceGetNew();
187 statp->fileType = CM_SCACHETYPE_DIRECTORY;
188 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME;
189 cm_PerformanceInsertToHashTable(statp);
192 if (volp->vol[ROVOL].ID) {
193 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
194 hash = fid.hash % fidStatsHashTableSize;
196 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
197 if (!cm_FidCmp(&fid, &statp->fid)) {
198 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
203 statp = cm_PerformanceGetNew();
205 statp->fileType = CM_SCACHETYPE_DIRECTORY;
206 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO;
207 cm_PerformanceInsertToHashTable(statp);
210 if (volp->vol[BACKVOL].ID) {
211 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
212 hash = fid.hash % fidStatsHashTableSize;
214 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
215 if (!cm_FidCmp(&fid, &statp->fid)) {
216 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
221 statp = cm_PerformanceGetNew();
223 statp->fileType = CM_SCACHETYPE_DIRECTORY;
224 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO;
225 cm_PerformanceInsertToHashTable(statp);
229 lock_ReleaseRead(&cm_volumeLock);
231 lock_ObtainRead(&buf_globalLock);
232 for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
235 if (bp->fid.cell == 0)
238 lock_ReleaseRead(&buf_globalLock);
239 scp = cm_FindSCache(&bp->fid);
241 lock_ObtainMutex(&bp->mx);
242 lock_ObtainRead(&scp->rw);
243 valid = cm_HaveBuffer(scp, bp, TRUE);
244 lock_ReleaseRead(&scp->rw);
245 lock_ReleaseMutex(&bp->mx);
246 cm_ReleaseSCache(scp);
249 hash = bp->fid.hash % fidStatsHashTableSize;
250 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
251 if (!cm_FidCmp(&bp->fid, &statp->fid)) {
258 lock_ObtainRead(&buf_globalLock);
260 lock_ReleaseRead(&buf_globalLock);
262 cm_PerformancePrintReport();
265 void cm_PerformanceTuningCheck(void)
273 cm_fid_stats_t * statp;
275 if (fidStatsHashTablep == NULL)
278 /* Clean all cm_fid_stat_t objects first */
279 for (i = 0; i < fidStatsHashTableSize; i++) {
280 for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) {
281 statp->flags &= (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO);
283 statp->fileLength.QuadPart = 0;
287 lock_ObtainRead(&cm_scacheLock);
288 for (i=0; i<cm_data.scacheHashTableSize; i++) {
289 for (scp=cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
290 if (scp->fid.cell == 0)
292 hash = scp->fid.hash % fidStatsHashTableSize;
294 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
295 if (!cm_FidCmp(&fid, &statp->fid)) {
296 statp->fileType = scp->fileType;
297 if (cm_HaveCallback(scp))
298 statp->flags |= CM_FIDSTATS_FLAG_CALLBACK;
299 statp->flags |= CM_FIDSTATS_FLAG_HAVE_SCACHE;
304 lock_ReleaseRead(&cm_scacheLock);
305 cm_PerformanceAddSCache(scp);
306 lock_ObtainRead(&cm_scacheLock);
310 lock_ReleaseRead(&cm_scacheLock);
312 lock_ObtainRead(&cm_volumeLock);
313 for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
314 if (volp->vol[RWVOL].ID) {
315 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
316 hash = fid.hash % fidStatsHashTableSize;
318 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
319 if (!cm_FidCmp(&fid, &statp->fid)) {
320 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
325 statp = cm_PerformanceGetNew();
327 statp->fileType = CM_SCACHETYPE_DIRECTORY;
328 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME;
329 cm_PerformanceInsertToHashTable(statp);
332 if (volp->vol[ROVOL].ID) {
333 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
334 hash = fid.hash % fidStatsHashTableSize;
336 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
337 if (!cm_FidCmp(&fid, &statp->fid)) {
338 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
343 statp = cm_PerformanceGetNew();
345 statp->fileType = CM_SCACHETYPE_DIRECTORY;
346 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO;
347 cm_PerformanceInsertToHashTable(statp);
350 if (volp->vol[BACKVOL].ID) {
351 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
352 hash = fid.hash % fidStatsHashTableSize;
354 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
355 if (!cm_FidCmp(&fid, &statp->fid)) {
356 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
361 statp = cm_PerformanceGetNew();
363 statp->fileType = CM_SCACHETYPE_DIRECTORY;
364 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO;
365 cm_PerformanceInsertToHashTable(statp);
369 lock_ReleaseRead(&cm_volumeLock);
371 lock_ObtainRead(&buf_globalLock);
372 for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
375 if (bp->fid.cell == 0)
378 lock_ReleaseRead(&buf_globalLock);
379 scp = cm_FindSCache(&bp->fid);
381 lock_ObtainMutex(&bp->mx);
382 lock_ObtainRead(&scp->rw);
383 valid = cm_HaveBuffer(scp, bp, TRUE);
384 lock_ReleaseRead(&scp->rw);
385 lock_ReleaseMutex(&bp->mx);
386 cm_ReleaseSCache(scp);
389 hash = bp->fid.hash % fidStatsHashTableSize;
390 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
391 if (!cm_FidCmp(&bp->fid, &statp->fid)) {
398 lock_ObtainRead(&buf_globalLock);
400 lock_ReleaseRead(&buf_globalLock);
402 cm_PerformancePrintReport();
405 void cm_PerformancePrintReport(void)
408 cm_fid_stats_t *statp;
410 afs_uint32 rw_vols = 0, ro_vols = 0, bk_vols = 0;
411 afs_uint32 fid_cnt = 0, fid_w_vol = 0, fid_w_scache = 0, fid_w_buffers = 0, fid_w_callbacks = 0;
412 afs_uint32 fid_w_scache_no_vol = 0, fid_w_scache_no_buf = 0, fid_w_vol_no_scache = 0, fid_w_buf_no_scache = 0;
413 afs_uint32 fid_file = 0, fid_dir = 0, fid_mp = 0, fid_sym = 0, fid_other = 0;
414 afs_uint32 fid_0k = 0, fid_1k = 0, fid_4k = 0, fid_64k = 0, fid_1m = 0, fid_20m = 0, fid_100m = 0, fid_1g = 0, fid_2g = 0, fid_large = 0;
417 char logfileName[MAX_PATH+1];
420 if (fidStatsHashTablep == NULL)
423 /* Clean all cm_fid_stat_t objects first */
424 for (i = 0; i < fidStatsHashTableSize; i++) {
425 for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) {
426 /* summarize the data */
429 if ((statp->flags & (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO)) == (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO))
431 else if (statp->flags & CM_FIDSTATS_FLAG_RO)
436 if (statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME)
439 if (statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE)
442 if (statp->flags & CM_FIDSTATS_FLAG_CALLBACK)
445 if (statp->buffers > 0)
448 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
449 !(statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME))
450 fid_w_scache_no_vol++;
452 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
454 fid_w_scache_no_buf++;
456 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME) &&
457 !(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE))
458 fid_w_vol_no_scache++;
460 if (!(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
462 fid_w_buf_no_scache++;
464 switch (statp->fileType) {
465 case CM_SCACHETYPE_FILE :
468 case CM_SCACHETYPE_DIRECTORY :
471 case CM_SCACHETYPE_SYMLINK :
474 case CM_SCACHETYPE_MOUNTPOINT :
477 case CM_SCACHETYPE_DFSLINK :
478 case CM_SCACHETYPE_INVALID :
483 if (statp->fileType == CM_SCACHETYPE_FILE) {
484 if (statp->fileLength.HighPart == 0) {
485 if (statp->fileLength.LowPart == 0)
487 else if (statp->fileLength.LowPart <= 1024)
489 else if (statp->fileLength.LowPart <= 4096)
491 else if (statp->fileLength.LowPart <= 65536)
493 else if (statp->fileLength.LowPart <= 1024*1024)
495 else if (statp->fileLength.LowPart <= 20*1024*1024)
497 else if (statp->fileLength.LowPart <= 100*1024*1024)
499 else if (statp->fileLength.LowPart <= 1024*1024*1024)
510 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
511 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
513 GetWindowsDirectory(logfileName, sizeof(logfileName));
515 strncat(logfileName, "\\afsd_performance.log", sizeof(logfileName));
517 hLogFile = CreateFile(logfileName, FILE_APPEND_DATA, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
518 FILE_ATTRIBUTE_NORMAL, NULL);
525 GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
527 StringCbPrintfA(output, sizeof(output),
529 "INUSE- stats=(%u of %u) vols=(%u of %u) bufs=(%I64u of %I64u)\r\n"
530 "FIDs - total=%u haveVol=%u haveStat=%u haveCB=%u haveBuf=%u haveStatNoVol=%u haveVolNoStat=%u haveStatNoBuf=%u haveBufNoStat=%u\r\n"
531 "VOLs - rw=%u ro=%u bk=%u\r\n"
532 "TYPEs- file=%u dir=%u mp=%u sym=%u unk=%u\r\n"
533 "SIZEs- 0kb=%u 1kb=%u 4kb=%u 64kb=%u 1mb=%u 20m=%u 100mb=%u 1gb=%u 2gb=%u larger=%u\r\n\r\n",
535 cm_data.currentSCaches, cm_data.maxSCaches, cm_data.currentVolumes, cm_data.maxVolumes,
536 cm_data.buf_nbuffers - buf_CountFreeList(), cm_data.buf_nbuffers,
537 fid_cnt, fid_w_vol, fid_w_scache, fid_w_callbacks, fid_w_buffers,
538 fid_w_scache_no_vol, fid_w_vol_no_scache, fid_w_scache_no_buf, fid_w_buf_no_scache,
539 rw_vols, ro_vols, bk_vols,
540 fid_file, fid_dir, fid_mp, fid_sym, fid_other,
541 fid_0k, fid_1k, fid_4k, fid_64k, fid_1m, fid_20m, fid_100m, fid_1g, fid_2g, fid_large
543 WriteFile(hLogFile, output, (DWORD)strlen(output), &zilch, NULL);
545 CloseHandle(hLogFile);