Changeset 80157 in vbox
- Timestamp:
- Aug 6, 2019 1:55:27 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132598
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/TM.cpp
r80142 r80157 145 145 146 146 #include <VBox/vmm/pdmdev.h> 147 #include <VBox/log.h> 147 148 #include <VBox/param.h> 148 149 #include <VBox/err.h> 149 150 150 #include <VBox/log.h>151 151 #include <iprt/asm.h> 152 152 #include <iprt/asm-math.h> 153 153 #include <iprt/assert.h> 154 #include <iprt/env.h> 154 155 #include <iprt/file.h> 156 #include <iprt/getopt.h> 157 #include <iprt/semaphore.h> 158 #include <iprt/string.h> 155 159 #include <iprt/thread.h> 156 160 #include <iprt/time.h> 157 161 #include <iprt/timer.h> 158 #include <iprt/semaphore.h>159 #include <iprt/string.h>160 #include <iprt/env.h>161 162 162 163 #include "TMInline.h" … … 187 188 static DECLCALLBACK(void) tmR3TimerInfoActive(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 188 189 static DECLCALLBACK(void) tmR3InfoClocks(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 189 static DECLCALLBACK(void) tmR3InfoCpuLoad(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);190 static DECLCALLBACK(void) tmR3InfoCpuLoad(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs); 190 191 static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtDisable(PVM pVM, PVMCPU pVCpu, void *pvData); 191 192 static const char * tmR3GetTSCModeName(PVM pVM); … … 855 856 DBGFR3InfoRegisterInternalEx(pVM, "activetimers", "Dumps active all timers. No arguments.", tmR3TimerInfoActive, DBGFINFO_FLAGS_RUN_ON_EMT); 856 857 DBGFR3InfoRegisterInternalEx(pVM, "clocks", "Display the time of the various clocks.", tmR3InfoClocks, DBGFINFO_FLAGS_RUN_ON_EMT); 857 DBGFR3InfoRegisterInternal Ex(pVM, "cpuload","Display the CPU load stats.", tmR3InfoCpuLoad, 0);858 DBGFR3InfoRegisterInternalArgv(pVM, "cpuload", "Display the CPU load stats.", tmR3InfoCpuLoad, 0); 858 859 859 860 return VINF_SUCCESS; … … 3760 3761 3761 3762 /** 3762 * @callback_function_impl{} 3763 */ 3764 static DECLCALLBACK(void) tmR3InfoCpuLoad(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs) 3765 { 3763 * Helper for tmR3InfoCpuLoad that adjust @a uPct to the given graph width. 3764 */ 3765 DECLINLINE(size_t) tmR3InfoCpuLoadAdjustWidth(size_t uPct, size_t cchWidth) 3766 { 3767 if (cchWidth != 100) 3768 uPct = (uPct + 0.5) * (cchWidth / 100.0); 3769 return uPct; 3770 } 3771 3772 3773 /** 3774 * @callback_function_impl{FNDBGFINFOARGVINT} 3775 */ 3776 static DECLCALLBACK(void) tmR3InfoCpuLoad(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs) 3777 { 3778 char szTmp[1024]; 3779 3766 3780 /* 3767 3781 * Parse arguments. 3768 3782 */ 3769 PTMCPULOADSTATE pState = &pVM->tm.s.CpuLoad; 3770 uint32_t cPeriods = 60; 3771 //uint32_t cchWidth = 100; 3772 3773 3774 RT_NOREF(pszArgs); /** @todo */ 3783 PTMCPULOADSTATE pState = &pVM->tm.s.CpuLoad; 3784 VMCPUID idCpu = VMCPUID_ALL; 3785 bool fExpGraph = true; 3786 uint32_t cchWidth = 100; 3787 uint32_t cPeriods = RT_ELEMENTS(pState->aHistory); 3788 uint32_t cRows = 60; 3789 3790 static const RTGETOPTDEF s_aOptions[] = 3791 { 3792 { "cpu", 'c', RTGETOPT_REQ_UINT32 }, 3793 { "periods", 'p', RTGETOPT_REQ_UINT32 }, 3794 { "linear", 'l', RTGETOPT_REQ_NOTHING }, 3795 { "rows", 'r', RTGETOPT_REQ_UINT32 }, 3796 { "width", 'w', RTGETOPT_REQ_UINT32 }, 3797 { "exp", 'x', RTGETOPT_REQ_NOTHING }, 3798 { "exponential", 'x', RTGETOPT_REQ_NOTHING }, 3799 }; 3800 3801 RTGETOPTSTATE State; 3802 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); 3803 AssertRC(rc); 3804 3805 RTGETOPTUNION ValueUnion; 3806 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0) 3807 { 3808 switch (rc) 3809 { 3810 case 'c': 3811 if (ValueUnion.u32 < pVM->cCpus) 3812 { 3813 pState = &pVM->aCpus[ValueUnion.u32].tm.s.CpuLoad; 3814 idCpu = ValueUnion.u32; 3815 } 3816 else 3817 { 3818 pState = &pVM->tm.s.CpuLoad; 3819 idCpu = VMCPUID_ALL; 3820 } 3821 break; 3822 case 'p': 3823 cPeriods = RT_MIN(RT_MAX(ValueUnion.u32, 1), RT_ELEMENTS(pState->aHistory)); 3824 break; 3825 case 'w': 3826 cchWidth = RT_MIN(RT_MAX(ValueUnion.u32, 10), sizeof(szTmp) - 32); 3827 break; 3828 case 'x': 3829 fExpGraph = true; 3830 break; 3831 case 'l': 3832 fExpGraph = false; 3833 break; 3834 case 'r': 3835 cRows = RT_MIN(RT_MAX(ValueUnion.u32, 5), RT_ELEMENTS(pState->aHistory)); 3836 break; 3837 default: 3838 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State); 3839 return; 3840 } 3841 } 3775 3842 3776 3843 /* … … 3782 3849 if (cPeriods > 0) 3783 3850 { 3784 size_t iHistory = (pState->idxHistory - cPeriods) % RT_ELEMENTS(pState->aHistory); 3851 /* 3852 * Figure number of periods per chunk. We can either do this in a linear 3853 * fashion or a exponential fashion that compresses old history more. 3854 */ 3855 size_t cPeriodsPerRow = 1; 3856 if (cRows < cPeriods) 3857 { 3858 if (fExpGraph) 3859 { 3860 /* The last 30 seconds or half of the rows are 1:1, the other part 3861 is in increasing period counts. Code is a little simple but seems 3862 to do the job most of the time, which is all I have time now. */ 3863 size_t cPeriodsOneToOne = RT_MIN(30, cRows / 2); 3864 size_t cRestRows = cRows - cPeriodsOneToOne; 3865 size_t cRestPeriods = cPeriods - cPeriodsOneToOne; 3866 3867 size_t cPeriodsInWindow = 0; 3868 for (cPeriodsPerRow = 0; cPeriodsPerRow <= cRestRows && cPeriodsInWindow < cRestPeriods; cPeriodsPerRow++) 3869 cPeriodsInWindow += cPeriodsPerRow + 1; 3870 3871 size_t iLower = 1; 3872 while (cPeriodsInWindow < cRestPeriods) 3873 { 3874 cPeriodsPerRow++; 3875 cPeriodsInWindow += cPeriodsPerRow; 3876 cPeriodsInWindow -= iLower; 3877 iLower++; 3878 } 3879 } 3880 else 3881 { 3882 cPeriodsPerRow = (cPeriods + cRows / 2) / cRows; 3883 } 3884 } 3885 3886 /* 3887 * Do the work. 3888 */ 3889 size_t cPctExecuting = 0; 3890 size_t cPctOther = 0; 3891 size_t cPeriodsAccumulated = 0; 3892 3893 size_t cRowsLeft = cRows; 3894 size_t iHistory = (pState->idxHistory - cPeriods) % RT_ELEMENTS(pState->aHistory); 3785 3895 while (cPeriods-- > 0) 3786 3896 { … … 3788 3898 if (iHistory >= RT_ELEMENTS(pState->aHistory)) 3789 3899 iHistory = 0; 3790 char szTmp[1024]; 3791 size_t offTmp = 0; 3792 size_t i = pState->aHistory[iHistory].cPctExecuting; 3793 while (i-- > 0) 3794 szTmp[offTmp++] = '#'; 3795 i = pState->aHistory[iHistory].cPctOther; 3796 while (i-- > 0) 3797 szTmp[offTmp++] = 'O'; 3798 szTmp[offTmp] = '\0'; 3799 pHlp->pfnPrintf(pHlp, "%2ds: %s\n", cPeriods, szTmp); 3900 3901 cPctExecuting += pState->aHistory[iHistory].cPctExecuting; 3902 cPctOther += pState->aHistory[iHistory].cPctOther; 3903 cPeriodsAccumulated += 1; 3904 if ( cPeriodsAccumulated >= cPeriodsPerRow 3905 || cPeriods < cRowsLeft) 3906 { 3907 /* 3908 * Format and output the line. 3909 */ 3910 size_t offTmp = 0; 3911 size_t i = tmR3InfoCpuLoadAdjustWidth(cPctExecuting / cPeriodsAccumulated, cchWidth); 3912 while (i-- > 0) 3913 szTmp[offTmp++] = '#'; 3914 i = tmR3InfoCpuLoadAdjustWidth(cPctOther / cPeriodsAccumulated, cchWidth); 3915 while (i-- > 0) 3916 szTmp[offTmp++] = 'O'; 3917 szTmp[offTmp] = '\0'; 3918 3919 cRowsLeft--; 3920 pHlp->pfnPrintf(pHlp, "%3zus: %s\n", cPeriods + cPeriodsAccumulated / 2, szTmp); 3921 3922 /* Reset the state: */ 3923 cPctExecuting = 0; 3924 cPctOther = 0; 3925 cPeriodsAccumulated = 0; 3926 if (cPeriodsPerRow > 1) 3927 cPeriodsPerRow--; 3928 } 3800 3929 } 3801 3930 pHlp->pfnPrintf(pHlp, " (#=guest, O=VMM overhead)\n");
Note:
See TracChangeset
for help on using the changeset viewer.