From: Jeffrey Altman Date: Fri, 7 Mar 2008 22:22:21 +0000 (+0000) Subject: windows-cm-performance-tuning-200803007 X-Git-Tag: BP-openafs-windows-kdfs-ifs~40 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=fdcf6bba5546f2a09e972323be9469a49ce04c6f;p=packages%2Fo%2Fopenafs.git windows-cm-performance-tuning-200803007 LICENSE MIT This is a first cut at a cache manager statistics monitor that can be used to determine the necessary cache parameters to support the working set. Off by default the performance package can be activated by setting "daemonPerformanceTuningInterval" in the service Parameters key. As with the other daemon interval values the unit is in seconds. At service start and each succeeding interval the cache manager will write statistics to %TEMP%\afsd_performance.txt showing the relative usage of cm_scache_t, cm_volume_t and cm_buf_t objects. The FID statistics keep track of all FIDs seen by the cache manager during the service session whether or not they are backed by any live object in the cache. These statistics are not stored in the cache file. --- diff --git a/src/WINNT/afsd/NTMakefile b/src/WINNT/afsd/NTMakefile index 9aab93144..bceb85506 100644 --- a/src/WINNT/afsd/NTMakefile +++ b/src/WINNT/afsd/NTMakefile @@ -63,6 +63,7 @@ INCFILES =\ $(INCFILEDIR)\cm_buf.h \ $(INCFILEDIR)\cm_freelance.h \ $(INCFILEDIR)\cm_memmap.h \ + $(INCFILEDIR)\cm_performance.h \ $(INCFILEDIR)\afsd_eventlog.h \ $(INCFILEDIR)\afsd_eventmessages.h \ $(INCFILEDIR)\afskfw.h \ @@ -124,6 +125,7 @@ AFSDOBJS=\ $(OUT)\cm_dnlc.obj \ $(OUT)\cm_rpc.obj \ $(OUT)\cm_memmap.obj \ + $(OUT)\cm_performance.obj \ $(OUT)\afsrpc_s.obj \ !IFDEF OSICRASH $(OUT)\afsdcrash.obj \ diff --git a/src/WINNT/afsd/afsd.h b/src/WINNT/afsd/afsd.h index 27d45edb0..ceeab6e26 100644 --- a/src/WINNT/afsd/afsd.h +++ b/src/WINNT/afsd/afsd.h @@ -53,6 +53,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long); #include "cm_buf.h" #include "cm_memmap.h" #include "cm_freelance.h" +#include "cm_performance.h" #include "smb_ioctl.h" #include "afsd_init.h" #include "afsd_eventlog.h" diff --git a/src/WINNT/afsd/cm_daemon.c b/src/WINNT/afsd/cm_daemon.c index 9ef65d4af..ccd34a3ce 100644 --- a/src/WINNT/afsd/cm_daemon.c +++ b/src/WINNT/afsd/cm_daemon.c @@ -34,6 +34,7 @@ long cm_daemonCheckVolCBInterval = 0; long cm_daemonCheckLockInterval = 60; long cm_daemonTokenCheckInterval = 180; long cm_daemonCheckOfflineVolInterval = 600; +long cm_daemonPerformanceTuningInterval = 0; osi_rwlock_t cm_daemonLock; @@ -273,60 +274,70 @@ cm_DaemonCheckInit(void) dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckDownInterval = dummy; afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckUpInterval = dummy; afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckVolInterval = dummy; afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckCBInterval = dummy; afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckVolCBInterval = dummy; afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckLockInterval = dummy; afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonTokenCheckInterval = dummy; afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval); dummyLen = sizeof(DWORD); code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL, (BYTE *) &dummy, &dummyLen); - if (code == ERROR_SUCCESS) + if (code == ERROR_SUCCESS && dummy) cm_daemonCheckOfflineVolInterval = dummy; afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval); + dummyLen = sizeof(DWORD); + code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL, + (BYTE *) &dummy, &dummyLen); + if (code == ERROR_SUCCESS) + cm_daemonPerformanceTuningInterval = dummy; + afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval); + RegCloseKey(parmKey); + + if (cm_daemonPerformanceTuningInterval) + cm_PerformanceTuningInit(); } /* periodic check daemon */ @@ -341,6 +352,7 @@ void cm_Daemon(long parm) time_t lastUpServerCheck; time_t lastTokenCacheCheck; time_t lastBusyVolCheck; + time_t lastPerformanceCheck; char thostName[200]; unsigned long code; struct hostent *thp; @@ -389,6 +401,8 @@ void cm_Daemon(long parm) lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval); lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval); lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval); + if (cm_daemonPerformanceTuningInterval) + lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval); while (daemon_ShutdownFlag == 0) { /* check to see if the listener threads halted due to network @@ -539,7 +553,18 @@ void cm_Daemon(long parm) if (daemon_ShutdownFlag == 1) { break; } - thrd_Sleep(10000); /* sleep 10 seconds */ + + if (cm_daemonPerformanceTuningInterval && + now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval && + daemon_ShutdownFlag == 0) { + lastPerformanceCheck = now; + cm_PerformanceTuningCheck(); + if (daemon_ShutdownFlag == 1) + break; + now = osi_Time(); + } + + thrd_Sleep(10000); /* sleep 10 seconds */ } thrd_SetEvent(cm_Daemon_ShutdownEvent); } diff --git a/src/WINNT/afsd/cm_performance.c b/src/WINNT/afsd/cm_performance.c new file mode 100644 index 000000000..f3f4e87a9 --- /dev/null +++ b/src/WINNT/afsd/cm_performance.c @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2008 - Secure Endpoints Inc. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "afsd.h" + +static cm_fid_stats_t ** fidStatsHashTablep = NULL; +static afs_uint32 fidStatsHashTableSize = 0; + +/* + * algorithm and implementation adapted from code written by + * Frank Pilhofer + */ +afs_uint32 nearest_prime(afs_uint32 s) +{ +#define TEST(f,x) (*(f+(x)/16)&(1<<(((x)%16L)/2))) +#define SET(f,x) *(f+(x)/16)|=1<<(((x)%16L)/2) + unsigned char *feld=NULL, *zzz; + afs_uint32 teste=1, mom, hits=1, count, max, alloc, largest_prime = 0; + + max = s + 10000L; + + while (feld==NULL) + zzz = feld = malloc (alloc=((max>>4)+1L)); + + for (count=0; countfid.hash % fidStatsHashTableSize; + + statp->nextp = fidStatsHashTablep[hash]; + fidStatsHashTablep[hash] = statp; +} + +void cm_PerformanceAddSCache(cm_scache_t *scp) +{ + cm_fid_stats_t * statp = cm_PerformanceGetNew(); + + if (!statp) + return; + + lock_ObtainRead(&scp->rw); + if (!(scp->flags & CM_SCACHEFLAG_DELETED)) { + statp->fid = scp->fid; + statp->fileLength = scp->length; + statp->fileType = scp->fileType; + statp->flags = CM_FIDSTATS_FLAG_HAVE_SCACHE; + if (cm_HaveCallback(scp)) + statp->flags |= CM_FIDSTATS_FLAG_CALLBACK; + if (scp->flags & CM_SCACHEFLAG_RO) + statp->flags |= CM_FIDSTATS_FLAG_RO; + if (scp->flags & CM_SCACHEFLAG_PURERO) + statp->flags |= CM_FIDSTATS_FLAG_PURERO; + } + lock_ReleaseRead(&scp->rw); + +#if 0 + if (statp->fid.vnode == 1) { + cm_volume_t *volp = NULL; + cm_cell_t *cellp = NULL; + cm_req_t req; + + cm_InitReq(&req); + + cellp = cm_FindCellByID(statp->fid.cell, 0); + if (cellp) { + if (!cm_GetVolumeByID(cellp, statp->fid.volume, cm_rootUserp, &req, 0, &volp)) { + statp->flags |= CM_FIDSTATS_HAVE_VOLUME; + cm_PutVolume(volp); + } + } + } +#endif + + cm_PerformanceInsertToHashTable(statp); +} + + +void cm_PerformanceTuningInit(void) +{ + afs_uint32 i; + cm_scache_t *scp; + cm_volume_t *volp; + cm_buf_t *bp; + cm_fid_t fid; + afs_uint32 hash; + cm_fid_stats_t * statp; + + fidStatsHashTableSize = nearest_prime(cm_data.stats/3); + if (fidStatsHashTableSize == 0) + fidStatsHashTableSize = cm_data.stats/3; + fidStatsHashTablep = (cm_fid_stats_t **)malloc(fidStatsHashTableSize * sizeof(cm_fid_stats_t *)); + if (fidStatsHashTablep == NULL) { + fidStatsHashTableSize = 0; + return; + } + + memset(fidStatsHashTablep, 0, fidStatsHashTableSize * sizeof(cm_fid_stats_t *)); + + lock_ObtainRead(&cm_scacheLock); + for (i=0; inextp) { + if (scp->fid.cell == 0) + continue; + cm_PerformanceAddSCache(scp); + } + } + lock_ReleaseRead(&cm_scacheLock); + + lock_ObtainRead(&cm_volumeLock); + for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) { + if (volp->rw.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->rw.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME; + cm_PerformanceInsertToHashTable(statp); + } + } + if (volp->ro.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->ro.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO; + cm_PerformanceInsertToHashTable(statp); + } + } + if (volp->bk.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->bk.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO; + cm_PerformanceInsertToHashTable(statp); + } + } + } + lock_ReleaseRead(&cm_volumeLock); + + lock_ObtainRead(&buf_globalLock); + for (bp = cm_data.buf_allp; bp; bp=bp->allp) { + int valid = 0; + + if (bp->fid.cell == 0) + continue; + + lock_ReleaseRead(&buf_globalLock); + scp = cm_FindSCache(&bp->fid); + if (scp) { + lock_ObtainMutex(&bp->mx); + lock_ObtainRead(&scp->rw); + valid = cm_HaveBuffer(scp, bp, TRUE); + lock_ReleaseRead(&scp->rw); + lock_ReleaseMutex(&bp->mx); + cm_ReleaseSCache(scp); + + if (valid) { + hash = bp->fid.hash % fidStatsHashTableSize; + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&bp->fid, &statp->fid)) { + statp->buffers++; + break; + } + } + } + } + lock_ObtainRead(&buf_globalLock); + } + lock_ReleaseRead(&buf_globalLock); + + cm_PerformancePrintReport(); +} + +void cm_PerformanceTuningCheck(void) +{ + afs_uint32 i; + cm_scache_t *scp; + cm_volume_t *volp; + cm_buf_t *bp; + cm_fid_t fid; + afs_uint32 hash; + cm_fid_stats_t * statp; + + if (fidStatsHashTablep == NULL) + return; + + /* Clean all cm_fid_stat_t objects first */ + for (i = 0; i < fidStatsHashTableSize; i++) { + for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) { + statp->flags &= (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO); + statp->buffers = 0; + statp->fileLength.QuadPart = 0; + } + } + + lock_ObtainRead(&cm_scacheLock); + for (i=0; inextp) { + if (scp->fid.cell == 0) + continue; + hash = scp->fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->fileType = scp->fileType; + if (cm_HaveCallback(scp)) + statp->flags |= CM_FIDSTATS_FLAG_CALLBACK; + statp->flags |= CM_FIDSTATS_FLAG_HAVE_SCACHE; + break; + } + } + if (!statp) + cm_PerformanceAddSCache(scp); + } + } + lock_ReleaseRead(&cm_scacheLock); + + lock_ObtainRead(&cm_volumeLock); + for(volp = cm_data.allVolumesp; volp; volp=volp->allNextp) { + if (volp->rw.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->rw.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME; + cm_PerformanceInsertToHashTable(statp); + } + } + if (volp->ro.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->ro.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO; + cm_PerformanceInsertToHashTable(statp); + } + } + if (volp->bk.ID) { + cm_SetFid(&fid, volp->cellp->cellID, volp->bk.ID, 1, 1); + hash = fid.hash % fidStatsHashTableSize; + + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&fid, &statp->fid)) { + statp->flags |= CM_FIDSTATS_FLAG_HAVE_VOLUME; + break; + } + } + if (!statp) { + statp = cm_PerformanceGetNew(); + statp->fid = fid; + statp->fileType = CM_SCACHETYPE_DIRECTORY; + statp->flags = CM_FIDSTATS_FLAG_HAVE_VOLUME | CM_FIDSTATS_FLAG_RO; + cm_PerformanceInsertToHashTable(statp); + } + } + } + lock_ReleaseRead(&cm_volumeLock); + + lock_ObtainRead(&buf_globalLock); + for (bp = cm_data.buf_allp; bp; bp=bp->allp) { + int valid = 0; + + if (bp->fid.cell == 0) + continue; + + lock_ReleaseRead(&buf_globalLock); + scp = cm_FindSCache(&bp->fid); + if (scp) { + lock_ObtainMutex(&bp->mx); + lock_ObtainRead(&scp->rw); + valid = cm_HaveBuffer(scp, bp, TRUE); + lock_ReleaseRead(&scp->rw); + lock_ReleaseMutex(&bp->mx); + cm_ReleaseSCache(scp); + + if (valid) { + hash = bp->fid.hash % fidStatsHashTableSize; + for (statp = fidStatsHashTablep[hash]; statp; statp = statp->nextp) { + if (!cm_FidCmp(&bp->fid, &statp->fid)) { + statp->buffers++; + break; + } + } + } + } + lock_ObtainRead(&buf_globalLock); + } + lock_ReleaseRead(&buf_globalLock); + + cm_PerformancePrintReport(); +} + +void cm_PerformancePrintReport(void) +{ + afs_uint32 i; + cm_fid_stats_t *statp; + + afs_uint32 rw_vols = 0, ro_vols = 0, bk_vols = 0; + afs_uint32 fid_cnt = 0, fid_w_vol = 0, fid_w_scache = 0, fid_w_buffers = 0, fid_w_callbacks = 0; + 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; + afs_uint32 fid_file = 0, fid_dir = 0, fid_mp = 0, fid_sym = 0, fid_other = 0; + 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; + + HANDLE hLogFile; + char logfileName[MAX_PATH+1]; + DWORD dwSize; + + if (fidStatsHashTablep == NULL) + return; + + /* Clean all cm_fid_stat_t objects first */ + for (i = 0; i < fidStatsHashTableSize; i++) { + for (statp = fidStatsHashTablep[i]; statp; statp = statp->nextp) { + /* summarize the data */ + fid_cnt++; + + if ((statp->flags & (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO)) == (CM_FIDSTATS_FLAG_RO | CM_FIDSTATS_FLAG_PURERO)) + ro_vols++; + else if (statp->flags & CM_FIDSTATS_FLAG_RO) + bk_vols++; + else + rw_vols++; + + if (statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME) + fid_w_vol++; + + if (statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) + fid_w_scache++; + + if (statp->flags & CM_FIDSTATS_FLAG_CALLBACK) + fid_w_callbacks++; + + if (statp->buffers > 0) + fid_w_buffers++; + + if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) && + !(statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME)) + fid_w_scache_no_vol++; + + if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) && + statp->buffers == 0) + fid_w_scache_no_buf++; + + if ((statp->flags & CM_FIDSTATS_FLAG_HAVE_VOLUME) && + !(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE)) + fid_w_vol_no_scache++; + + if (!(statp->flags & CM_FIDSTATS_FLAG_HAVE_SCACHE) && + statp->buffers > 0) + fid_w_buf_no_scache++; + + switch (statp->fileType) { + case CM_SCACHETYPE_FILE : + fid_file++; + break; + case CM_SCACHETYPE_DIRECTORY : + fid_dir++; + break; + case CM_SCACHETYPE_SYMLINK : + fid_sym++; + break; + case CM_SCACHETYPE_MOUNTPOINT : + fid_mp++; + break; + case CM_SCACHETYPE_DFSLINK : + case CM_SCACHETYPE_INVALID : + default: + fid_other++; + } + + if (statp->fileType == CM_SCACHETYPE_FILE) { + if (statp->fileLength.HighPart == 0) { + if (statp->fileLength.LowPart == 0) + fid_0k++; + else if (statp->fileLength.LowPart <= 1024) + fid_1k++; + else if (statp->fileLength.LowPart <= 4096) + fid_4k++; + else if (statp->fileLength.LowPart <= 65536) + fid_64k++; + else if (statp->fileLength.LowPart <= 1024*1024) + fid_1m++; + else if (statp->fileLength.LowPart <= 20*1024*1024) + fid_20m++; + else if (statp->fileLength.LowPart <= 100*1024*1024) + fid_100m++; + else if (statp->fileLength.LowPart <= 1024*1024*1024) + fid_1g++; + else + fid_2g++; + } else { + fid_large++; + } + } + } + } + + dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName)); + if ( dwSize == 0 || dwSize > sizeof(logfileName) ) + { + GetWindowsDirectory(logfileName, sizeof(logfileName)); + } + strncat(logfileName, "\\afsd_performance.log", sizeof(logfileName)); + + hLogFile = CreateFile(logfileName, FILE_APPEND_DATA, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (hLogFile) { + char output[1024]; + char t[100]; + int zilch; + + GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t)); + + StringCbPrintfA(output, sizeof(output), + "TIME - %s\r\n" + "INUSE- stats=(%u of %u) vols=(%u of %u) bufs=(%I64u of %I64u)\r\n" + "FIDs - total=%u haveVol=%u haveStat=%u haveCB=%u haveBuf=%u haveStatNoVol=%u haveVolNoStat=%u haveStatNoBuf=%u haveBufNoStat=%u\r\n" + "VOLs - rw=%u ro=%u bk=%u\r\n" + "TYPEs- file=%u dir=%u mp=%u sym=%u unk=%u\r\n" + "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", + t, + cm_data.currentSCaches, cm_data.maxSCaches, cm_data.currentVolumes, cm_data.maxVolumes, + cm_data.buf_nbuffers - buf_CountFreeList(), cm_data.buf_nbuffers, + fid_cnt, fid_w_vol, fid_w_scache, fid_w_callbacks, fid_w_buffers, + fid_w_scache_no_vol, fid_w_vol_no_scache, fid_w_scache_no_buf, fid_w_buf_no_scache, + rw_vols, ro_vols, bk_vols, + fid_file, fid_dir, fid_mp, fid_sym, fid_other, + fid_0k, fid_1k, fid_4k, fid_64k, fid_1m, fid_20m, fid_100m, fid_1g, fid_2g, fid_large + ); + WriteFile(hLogFile, output, (DWORD)strlen(output), &zilch, NULL); + + CloseHandle(hLogFile); + } + + +} diff --git a/src/WINNT/afsd/cm_performance.h b/src/WINNT/afsd/cm_performance.h new file mode 100644 index 000000000..afcc11a13 --- /dev/null +++ b/src/WINNT/afsd/cm_performance.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008 - Secure Endpoints Inc. + */ + +/* + * The performance module when activated collects + * data necessary to analyze the usage of the cache + * manager and establish recommendations for future + * cache manager configuration changes. + * + * As a starting point, the package will collect + * a list of all FIDs accessed during the session + * which will be used to periodically analyzed the + * contents of the cm_buf_t, cm_scache_t, cm_volume_t + * and cm_cell_t pools. + + */ + +typedef struct cm_fid_stats { + cm_fid_t fid; + afs_uint32 fileType; + osi_hyper_t fileLength; + afs_uint32 flags; + afs_uint32 buffers; + struct cm_fid_stats * nextp; +} cm_fid_stats_t; + +#define CM_FIDSTATS_FLAG_HAVE_SCACHE 0x01 /* set if cm_scache_t present */ +#define CM_FIDSTATS_FLAG_HAVE_VOLUME 0x02 /* set on (vnode = 1) if cm_vol_t present */ +#define CM_FIDSTATS_FLAG_RO 0x04 +#define CM_FIDSTATS_FLAG_PURERO 0x08 +#define CM_FIDSTATS_FLAG_CALLBACK 0x10 + +extern void cm_PerformanceTuningCheck(void); + +extern void cm_PerformancePrintReport(void); +