2 * Copyright (c) 2008 - Secure Endpoints Inc.
21 static cm_fid_stats_t ** fidStatsHashTablep = NULL;
22 static afs_uint32 fidStatsHashTableSize = 0;
25 * algorithm and implementation adapted from code written by
26 * Frank Pilhofer <fp@fpx.de>
28 afs_uint32 nearest_prime(afs_uint32 s)
30 #define TEST(f,x) (*(f+(x)/16)&(1<<(((x)%16L)/2)))
31 #define SET(f,x) *(f+(x)/16)|=1<<(((x)%16L)/2)
32 unsigned char *feld=NULL, *zzz;
33 afs_uint32 teste=1, mom, hits=1, count, max, alloc, largest_prime = 0;
38 zzz = feld = malloc (alloc=((max>>4)+1L));
40 for (count=0; count<alloc; count++)
43 while ((teste+=2) < max) {
44 if (!TEST(feld, teste)) {
45 for (mom=3L*teste; mom<max; mom+=teste<<1)
53 while ((count+=2)<max) {
54 if (!TEST(feld,count)) {
55 largest_prime = count;
63 /* We never free these objects so we don't need to
64 * worry about reuse or tracking the allocations
66 * The management of the free allocation is not
67 * thread safe because we never expect this code
68 * to be called from more than one thread.
70 cm_fid_stats_t * cm_PerformanceGetNew(void)
72 static cm_fid_stats_t * allocp = NULL;
73 static afs_int32 allocSize = 0;
74 static afs_int32 nextFree = 0;
76 if (nextFree < allocSize)
77 return &allocp[nextFree++];
79 allocp = (cm_fid_stats_t *)malloc(32768);
83 allocSize = 32768/sizeof(cm_fid_stats_t);
84 memset(allocp, 0, 32768);
89 void cm_PerformanceInsertToHashTable(cm_fid_stats_t *statp)
91 afs_uint32 hash = statp->fid.hash % fidStatsHashTableSize;
93 statp->nextp = fidStatsHashTablep[hash];
94 fidStatsHashTablep[hash] = statp;
97 void cm_PerformanceAddSCache(cm_scache_t *scp)
99 cm_fid_stats_t * statp = cm_PerformanceGetNew();
104 lock_ObtainRead(&scp->rw);
105 if (!(scp->flags & CM_SCACHEFLAG_DELETED)) {
106 statp->fid = scp->fid;
107 statp->fileLength = scp->length;
108 statp->fileType = scp->fileType;
109 statp->flags = CM_FIDSTATS_FLAG_HAVE_SCACHE;
110 lock_ConvertRToW(&scp->rw);
111 if (cm_HaveCallback(scp))
112 statp->flags |= CM_FIDSTATS_FLAG_CALLBACK;
113 lock_ConvertWToR(&scp->rw);
114 if (scp->flags & CM_SCACHEFLAG_RO)
115 statp->flags |= CM_FIDSTATS_FLAG_RO;
116 if (scp->flags & CM_SCACHEFLAG_PURERO)
117 statp->flags |= CM_FIDSTATS_FLAG_PURERO;
119 lock_ReleaseRead(&scp->rw);
122 if (statp->fid.vnode == 1) {
123 cm_volume_t *volp = NULL;
124 cm_cell_t *cellp = NULL;
129 cellp = cm_FindCellByID(statp->fid.cell, 0);
131 if (!cm_FindVolumeByID(cellp, statp->fid.volume, cm_rootUserp, &req, 0, &volp)) {
132 statp->flags |= CM_FIDSTATS_HAVE_VOLUME;
139 cm_PerformanceInsertToHashTable(statp);
143 void cm_PerformanceTuningInit(void)
151 cm_fid_stats_t * statp;
153 fidStatsHashTableSize = nearest_prime(cm_data.stats/3);
154 if (fidStatsHashTableSize == 0)
155 fidStatsHashTableSize = cm_data.stats/3;
156 fidStatsHashTablep = (cm_fid_stats_t **)malloc(fidStatsHashTableSize * sizeof(cm_fid_stats_t *));
157 if (fidStatsHashTablep == NULL) {
158 fidStatsHashTableSize = 0;
162 memset(fidStatsHashTablep, 0, fidStatsHashTableSize * sizeof(cm_fid_stats_t *));
164 lock_ObtainRead(&cm_scacheLock);
165 for (i=0; i<cm_data.scacheHashTableSize; i++) {
166 for (scp=cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
167 if (scp->fid.cell == 0)
169 lock_ReleaseRead(&cm_scacheLock);
170 cm_PerformanceAddSCache(scp);
171 lock_ObtainRead(&cm_scacheLock);
174 lock_ReleaseRead(&cm_scacheLock);
176 lock_ObtainRead(&cm_volumeLock);
177 for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
178 if (volp->vol[RWVOL].ID) {
179 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
180 hash = fid.hash % fidStatsHashTableSize;
182 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
183 if (!cm_FidCmp(&fid, &statp->fid)) {
184 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
189 statp = cm_PerformanceGetNew();
191 statp->fileType = CM_SCACHETYPE_DIRECTORY;
192 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME;
193 cm_PerformanceInsertToHashTable(statp);
196 if (volp->vol[ROVOL].ID) {
197 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
198 hash = fid.hash % fidStatsHashTableSize;
200 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
201 if (!cm_FidCmp(&fid, &statp->fid)) {
202 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
207 statp = cm_PerformanceGetNew();
209 statp->fileType = CM_SCACHETYPE_DIRECTORY;
210 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO;
211 cm_PerformanceInsertToHashTable(statp);
214 if (volp->vol[BACKVOL].ID) {
215 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
216 hash = fid.hash % fidStatsHashTableSize;
218 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
219 if (!cm_FidCmp(&fid, &statp->fid)) {
220 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
225 statp = cm_PerformanceGetNew();
227 statp->fileType = CM_SCACHETYPE_DIRECTORY;
228 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO;
229 cm_PerformanceInsertToHashTable(statp);
233 lock_ReleaseRead(&cm_volumeLock);
235 lock_ObtainRead(&buf_globalLock);
236 for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
239 if (bp->fid.cell == 0)
242 lock_ReleaseRead(&buf_globalLock);
243 scp = cm_FindSCache(&bp->fid);
245 lock_ObtainMutex(&bp->mx);
246 lock_ObtainRead(&scp->rw);
247 valid = cm_HaveBuffer(scp, bp, TRUE);
248 lock_ReleaseRead(&scp->rw);
249 lock_ReleaseMutex(&bp->mx);
250 cm_ReleaseSCache(scp);
253 hash = bp->fid.hash % fidStatsHashTableSize;
254 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
255 if (!cm_FidCmp(&bp->fid, &statp->fid)) {
262 lock_ObtainRead(&buf_globalLock);
264 lock_ReleaseRead(&buf_globalLock);
266 cm_PerformancePrintReport();
269 void cm_PerformanceTuningCheck(void)
277 cm_fid_stats_t * statp;
279 if (fidStatsHashTablep == NULL)
282 /* Clean all cm_fid_stat_t objects first */
283 for (i = 0; i < fidStatsHashTableSize; i++) {
284 for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) {
285 statp->flags &= (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO);
287 statp->fileLength.QuadPart = 0;
291 lock_ObtainRead(&cm_scacheLock);
292 for (i=0; i<cm_data.scacheHashTableSize; i++) {
293 for (scp=cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
294 if (scp->fid.cell == 0)
296 hash = scp->fid.hash % fidStatsHashTableSize;
298 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
299 if (!cm_FidCmp(&fid, &statp->fid)) {
300 statp->fileType = scp->fileType;
301 if (cm_HaveCallback(scp))
302 statp->flags |= CM_FIDSTATS_FLAG_CALLBACK;
303 statp->flags |= CM_FIDSTATS_FLAG_HAVE_SCACHE;
308 lock_ReleaseRead(&cm_scacheLock);
309 cm_PerformanceAddSCache(scp);
310 lock_ObtainRead(&cm_scacheLock);
314 lock_ReleaseRead(&cm_scacheLock);
316 lock_ObtainRead(&cm_volumeLock);
317 for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
318 if (volp->vol[RWVOL].ID) {
319 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[RWVOL].ID, 1, 1);
320 hash = fid.hash % fidStatsHashTableSize;
322 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
323 if (!cm_FidCmp(&fid, &statp->fid)) {
324 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
329 statp = cm_PerformanceGetNew();
331 statp->fileType = CM_SCACHETYPE_DIRECTORY;
332 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME;
333 cm_PerformanceInsertToHashTable(statp);
336 if (volp->vol[ROVOL].ID) {
337 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[ROVOL].ID, 1, 1);
338 hash = fid.hash % fidStatsHashTableSize;
340 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
341 if (!cm_FidCmp(&fid, &statp->fid)) {
342 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
347 statp = cm_PerformanceGetNew();
349 statp->fileType = CM_SCACHETYPE_DIRECTORY;
350 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO;
351 cm_PerformanceInsertToHashTable(statp);
354 if (volp->vol[BACKVOL].ID) {
355 cm_SetFid(&fid, volp->cellp->cellID, volp->vol[BACKVOL].ID, 1, 1);
356 hash = fid.hash % fidStatsHashTableSize;
358 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
359 if (!cm_FidCmp(&fid, &statp->fid)) {
360 statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME;
365 statp = cm_PerformanceGetNew();
367 statp->fileType = CM_SCACHETYPE_DIRECTORY;
368 statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO;
369 cm_PerformanceInsertToHashTable(statp);
373 lock_ReleaseRead(&cm_volumeLock);
375 lock_ObtainRead(&buf_globalLock);
376 for (bp = cm_data.buf_allp; bp; bp=bp->allp) {
379 if (bp->fid.cell == 0)
382 lock_ReleaseRead(&buf_globalLock);
383 scp = cm_FindSCache(&bp->fid);
385 lock_ObtainMutex(&bp->mx);
386 lock_ObtainRead(&scp->rw);
387 valid = cm_HaveBuffer(scp, bp, TRUE);
388 lock_ReleaseRead(&scp->rw);
389 lock_ReleaseMutex(&bp->mx);
390 cm_ReleaseSCache(scp);
393 hash = bp->fid.hash % fidStatsHashTableSize;
394 for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) {
395 if (!cm_FidCmp(&bp->fid, &statp->fid)) {
402 lock_ObtainRead(&buf_globalLock);
404 lock_ReleaseRead(&buf_globalLock);
406 cm_PerformancePrintReport();
409 void cm_PerformancePrintReport(void)
412 cm_fid_stats_t *statp;
414 afs_uint32 rw_vols = 0, ro_vols = 0, bk_vols = 0;
415 afs_uint32 fid_cnt = 0, fid_w_vol = 0, fid_w_scache = 0, fid_w_buffers = 0, fid_w_callbacks = 0;
416 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;
417 afs_uint32 fid_file = 0, fid_dir = 0, fid_mp = 0, fid_sym = 0, fid_other = 0;
418 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;
421 char logfileName[MAX_PATH+1];
424 if (fidStatsHashTablep == NULL)
427 /* Clean all cm_fid_stat_t objects first */
428 for (i = 0; i < fidStatsHashTableSize; i++) {
429 for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) {
430 /* summarize the data */
433 if ((statp->flags & (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO)) == (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO))
435 else if (statp->flags & CM_FIDSTATS_FLAG_RO)
440 if (statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME)
443 if (statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE)
446 if (statp->flags & CM_FIDSTATS_FLAG_CALLBACK)
449 if (statp->buffers > 0)
452 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
453 !(statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME))
454 fid_w_scache_no_vol++;
456 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
458 fid_w_scache_no_buf++;
460 if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME) &&
461 !(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE))
462 fid_w_vol_no_scache++;
464 if (!(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) &&
466 fid_w_buf_no_scache++;
468 switch (statp->fileType) {
469 case CM_SCACHETYPE_FILE :
472 case CM_SCACHETYPE_DIRECTORY :
475 case CM_SCACHETYPE_SYMLINK :
478 case CM_SCACHETYPE_MOUNTPOINT :
481 case CM_SCACHETYPE_DFSLINK :
482 case CM_SCACHETYPE_INVALID :
487 if (statp->fileType == CM_SCACHETYPE_FILE) {
488 if (statp->fileLength.HighPart == 0) {
489 if (statp->fileLength.LowPart == 0)
491 else if (statp->fileLength.LowPart <= 1024)
493 else if (statp->fileLength.LowPart <= 4096)
495 else if (statp->fileLength.LowPart <= 65536)
497 else if (statp->fileLength.LowPart <= 1024*1024)
499 else if (statp->fileLength.LowPart <= 20*1024*1024)
501 else if (statp->fileLength.LowPart <= 100*1024*1024)
503 else if (statp->fileLength.LowPart <= 1024*1024*1024)
514 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
515 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
517 GetWindowsDirectory(logfileName, sizeof(logfileName));
519 strncat(logfileName, "\\afsd_performance.log", sizeof(logfileName));
521 hLogFile = CreateFile(logfileName, FILE_APPEND_DATA, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
522 FILE_ATTRIBUTE_NORMAL, NULL);
529 GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
531 StringCbPrintfA(output, sizeof(output),
533 "INUSE- stats=(%u of %u) vols=(%u of %u) bufs=(%I64u of %I64u)\r\n"
534 "FIDs - total=%u haveVol=%u haveStat=%u haveCB=%u haveBuf=%u haveStatNoVol=%u haveVolNoStat=%u haveStatNoBuf=%u haveBufNoStat=%u\r\n"
535 "VOLs - rw=%u ro=%u bk=%u\r\n"
536 "TYPEs- file=%u dir=%u mp=%u sym=%u unk=%u\r\n"
537 "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",
539 cm_data.currentSCaches, cm_data.maxSCaches, cm_data.currentVolumes, cm_data.maxVolumes,
540 cm_data.buf_nbuffers - cm_data.buf_freeCount, cm_data.buf_nbuffers,
541 fid_cnt, fid_w_vol, fid_w_scache, fid_w_callbacks, fid_w_buffers,
542 fid_w_scache_no_vol, fid_w_vol_no_scache, fid_w_scache_no_buf, fid_w_buf_no_scache,
543 rw_vols, ro_vols, bk_vols,
544 fid_file, fid_dir, fid_mp, fid_sym, fid_other,
545 fid_0k, fid_1k, fid_4k, fid_64k, fid_1m, fid_20m, fid_100m, fid_1g, fid_2g, fid_large
547 WriteFile(hLogFile, output, (DWORD)strlen(output), &zilch, NULL);
549 CloseHandle(hLogFile);