Changeset 80159 in vbox
- Timestamp:
- Aug 6, 2019 3:32:11 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132600
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/TM.cpp
r80157 r80159 856 856 DBGFR3InfoRegisterInternalEx(pVM, "activetimers", "Dumps active all timers. No arguments.", tmR3TimerInfoActive, DBGFINFO_FLAGS_RUN_ON_EMT); 857 857 DBGFR3InfoRegisterInternalEx(pVM, "clocks", "Display the time of the various clocks.", tmR3InfoClocks, DBGFINFO_FLAGS_RUN_ON_EMT); 858 DBGFR3InfoRegisterInternalArgv(pVM, "cpuload", "Display the CPU load stats .", tmR3InfoCpuLoad,0);858 DBGFR3InfoRegisterInternalArgv(pVM, "cpuload", "Display the CPU load stats (--help for details).", tmR3InfoCpuLoad, 0); 859 859 860 860 return VINF_SUCCESS; … … 3782 3782 */ 3783 3783 PTMCPULOADSTATE pState = &pVM->tm.s.CpuLoad; 3784 VMCPUID idCpu = VMCPUID_ALL; 3784 VMCPUID idCpu = 0; 3785 bool fAllCpus = true; 3785 3786 bool fExpGraph = true; 3786 uint32_t cchWidth = 100;3787 uint32_t cchWidth = 80; 3787 3788 uint32_t cPeriods = RT_ELEMENTS(pState->aHistory); 3788 3789 uint32_t cRows = 60; … … 3790 3791 static const RTGETOPTDEF s_aOptions[] = 3791 3792 { 3793 { "all", 'a', RTGETOPT_REQ_NOTHING }, 3792 3794 { "cpu", 'c', RTGETOPT_REQ_UINT32 }, 3793 3795 { "periods", 'p', RTGETOPT_REQ_UINT32 }, 3794 { "linear", 'l', RTGETOPT_REQ_NOTHING },3795 3796 { "rows", 'r', RTGETOPT_REQ_UINT32 }, 3797 { "uni", 'u', RTGETOPT_REQ_NOTHING }, 3798 { "uniform", 'u', RTGETOPT_REQ_NOTHING }, 3796 3799 { "width", 'w', RTGETOPT_REQ_UINT32 }, 3797 3800 { "exp", 'x', RTGETOPT_REQ_NOTHING }, … … 3800 3803 3801 3804 RTGETOPTSTATE State; 3802 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);3805 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0 /*fFlags*/); 3803 3806 AssertRC(rc); 3804 3807 … … 3808 3811 switch (rc) 3809 3812 { 3813 case 'a': 3814 pState = &pVM->aCpus[0].tm.s.CpuLoad; 3815 idCpu = 0; 3816 fAllCpus = true; 3817 break; 3810 3818 case 'c': 3811 3819 if (ValueUnion.u32 < pVM->cCpus) … … 3819 3827 idCpu = VMCPUID_ALL; 3820 3828 } 3829 fAllCpus = false; 3821 3830 break; 3822 3831 case 'p': 3823 3832 cPeriods = RT_MIN(RT_MAX(ValueUnion.u32, 1), RT_ELEMENTS(pState->aHistory)); 3833 break; 3834 case 'r': 3835 cRows = RT_MIN(RT_MAX(ValueUnion.u32, 5), RT_ELEMENTS(pState->aHistory)); 3824 3836 break; 3825 3837 case 'w': … … 3829 3841 fExpGraph = true; 3830 3842 break; 3831 case ' l':3843 case 'u': 3832 3844 fExpGraph = false; 3833 3845 break; 3834 case 'r': 3835 cRows = RT_MIN(RT_MAX(ValueUnion.u32, 5), RT_ELEMENTS(pState->aHistory)); 3836 break; 3846 case 'h': 3847 pHlp->pfnPrintf(pHlp, 3848 "Usage: cpuload [parameters]\n" 3849 " all, -a\n" 3850 " Show statistics for all CPUs. (default)\n" 3851 " cpu=id, -c id\n" 3852 " Show statistics for the specified CPU ID. Show combined stats if out of range.\n" 3853 " periods=count, -p count\n" 3854 " Number of periods to show. Default: all\n" 3855 " rows=count, -r count\n" 3856 " Number of rows in the graphs. Default: 60\n" 3857 " width=count, -w count\n" 3858 " Core graph width in characters. Default: 80\n" 3859 " exp, exponential, -e\n" 3860 " Do 1:1 for more recent half / 30 seconds of the graph, combine the\n" 3861 " rest into increasinly larger chunks. Default.\n" 3862 " uniform, uni, -u\n" 3863 " Combine periods into rows in a uniform manner for the whole graph.\n"); 3864 return; 3837 3865 default: 3838 3866 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State); … … 3842 3870 3843 3871 /* 3844 * Try do the job. 3845 */ 3846 uint32_t const cMaxPeriods = pState->cHistoryEntries; 3847 if (cPeriods > cMaxPeriods) 3848 cPeriods = cMaxPeriods; 3849 if (cPeriods > 0) 3850 { 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) 3872 * Do the job. 3873 */ 3874 for (;;) 3875 { 3876 uint32_t const cMaxPeriods = pState->cHistoryEntries; 3877 if (cPeriods > cMaxPeriods) 3878 cPeriods = cMaxPeriods; 3879 if (cPeriods > 0) 3857 3880 { 3858 if (f ExpGraph)3881 if (fAllCpus) 3859 3882 { 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) 3883 if (idCpu > 0) 3884 pHlp->pfnPrintf(pHlp, "\n"); 3885 pHlp->pfnPrintf(pHlp, " CPU load for virtual CPU %#04x\n" 3886 " -------------------------------\n", idCpu); 3887 } 3888 3889 /* 3890 * Figure number of periods per chunk. We can either do this in a linear 3891 * fashion or a exponential fashion that compresses old history more. 3892 */ 3893 size_t cPerRowDecrement = 0; 3894 size_t cPeriodsPerRow = 1; 3895 if (cRows < cPeriods) 3896 { 3897 if (!fExpGraph) 3898 cPeriodsPerRow = (cPeriods + cRows / 2) / cRows; 3899 else 3873 3900 { 3874 cPeriodsPerRow++; 3875 cPeriodsInWindow += cPeriodsPerRow; 3876 cPeriodsInWindow -= iLower; 3877 iLower++; 3901 /* The last 30 seconds or half of the rows are 1:1, the other part 3902 is in increasing period counts. Code is a little simple but seems 3903 to do the job most of the time, which is all I have time now. */ 3904 size_t cPeriodsOneToOne = RT_MIN(30, cRows / 2); 3905 size_t cRestRows = cRows - cPeriodsOneToOne; 3906 size_t cRestPeriods = cPeriods - cPeriodsOneToOne; 3907 3908 size_t cPeriodsInWindow = 0; 3909 for (cPeriodsPerRow = 0; cPeriodsPerRow <= cRestRows && cPeriodsInWindow < cRestPeriods; cPeriodsPerRow++) 3910 cPeriodsInWindow += cPeriodsPerRow + 1; 3911 3912 size_t iLower = 1; 3913 while (cPeriodsInWindow < cRestPeriods) 3914 { 3915 cPeriodsPerRow++; 3916 cPeriodsInWindow += cPeriodsPerRow; 3917 cPeriodsInWindow -= iLower; 3918 iLower++; 3919 } 3920 3921 cPerRowDecrement = 1; 3878 3922 } 3879 3923 } 3880 else 3924 3925 /* 3926 * Do the work. 3927 */ 3928 size_t cPctExecuting = 0; 3929 size_t cPctOther = 0; 3930 size_t cPeriodsAccumulated = 0; 3931 3932 size_t cRowsLeft = cRows; 3933 size_t iHistory = (pState->idxHistory - cPeriods) % RT_ELEMENTS(pState->aHistory); 3934 while (cPeriods-- > 0) 3881 3935 { 3882 cPeriodsPerRow = (cPeriods + cRows / 2) / cRows; 3936 iHistory++; 3937 if (iHistory >= RT_ELEMENTS(pState->aHistory)) 3938 iHistory = 0; 3939 3940 cPctExecuting += pState->aHistory[iHistory].cPctExecuting; 3941 cPctOther += pState->aHistory[iHistory].cPctOther; 3942 cPeriodsAccumulated += 1; 3943 if ( cPeriodsAccumulated >= cPeriodsPerRow 3944 || cPeriods < cRowsLeft) 3945 { 3946 /* 3947 * Format and output the line. 3948 */ 3949 size_t offTmp = 0; 3950 size_t i = tmR3InfoCpuLoadAdjustWidth(cPctExecuting / cPeriodsAccumulated, cchWidth); 3951 while (i-- > 0) 3952 szTmp[offTmp++] = '#'; 3953 i = tmR3InfoCpuLoadAdjustWidth(cPctOther / cPeriodsAccumulated, cchWidth); 3954 while (i-- > 0) 3955 szTmp[offTmp++] = 'O'; 3956 szTmp[offTmp] = '\0'; 3957 3958 cRowsLeft--; 3959 pHlp->pfnPrintf(pHlp, "%3zus: %s\n", cPeriods + cPeriodsAccumulated / 2, szTmp); 3960 3961 /* Reset the state: */ 3962 cPctExecuting = 0; 3963 cPctOther = 0; 3964 cPeriodsAccumulated = 0; 3965 if (cPeriodsPerRow > cPerRowDecrement) 3966 cPeriodsPerRow -= cPerRowDecrement; 3967 } 3883 3968 } 3969 pHlp->pfnPrintf(pHlp, " (#=guest, O=VMM overhead) idCpu=%#x\n", idCpu); 3970 3884 3971 } 3972 else 3973 pHlp->pfnPrintf(pHlp, "No load data.\n"); 3885 3974 3886 3975 /* 3887 * Do the work.3976 * Next CPU if we're display all. 3888 3977 */ 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); 3895 while (cPeriods-- > 0) 3896 { 3897 iHistory++; 3898 if (iHistory >= RT_ELEMENTS(pState->aHistory)) 3899 iHistory = 0; 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 } 3929 } 3930 pHlp->pfnPrintf(pHlp, " (#=guest, O=VMM overhead)\n"); 3931 3932 } 3933 else 3934 pHlp->pfnPrintf(pHlp, "No load data.\n"); 3978 if (!fAllCpus) 3979 break; 3980 idCpu++; 3981 if (idCpu >= pVM->cCpus) 3982 break; 3983 pState = &pVM->aCpus[idCpu].tm.s.CpuLoad; 3984 } 3985 3935 3986 } 3936 3987
Note:
See TracChangeset
for help on using the changeset viewer.