📄 pvrhddbenchdlg.cpp
字号:
// PvrHDDBenchDlg.cpp : implementation file
//
#include "stdafx.h"
#include "PvrHDDBench.h"
#include "PvrHDDBenchDlg.h"
#include <winioctl.h>
#include "vcplot.h"
#include "vcaxis.h"
#include "vcaxisscale.h"
#include "vctick.h"
#include "vcvaluescale.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPvrHDDBenchDlg dialog
CPvrHDDBenchDlg::CPvrHDDBenchDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPvrHDDBenchDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPvrHDDBenchDlg)
m_StrCurDrive = _T("NO DRIVE SELECTED");
m_BlkSize = 4;
m_NrOfRW = 16;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_CurHDD = -1; // no drive selected
m_hSelectedDrive = INVALID_HANDLE_VALUE;
}
void CPvrHDDBenchDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPvrHDDBenchDlg)
DDX_Control(pDX, IDC_PROGRESS, m_Progress);
DDX_Control(pDX, IDC_HDDLIST, m_HDDList);
DDX_Text(pDX, IDC_DRIVEID, m_StrCurDrive);
DDX_Control(pDX, IDC_MSCHART2, m_Chart);
DDX_Text(pDX, IDC_BLKSIZE, m_BlkSize);
DDV_MinMaxDWord(pDX, m_BlkSize, 4, 1024);
DDX_Text(pDX, IDC_NROFRW, m_NrOfRW);
DDV_MinMaxDWord(pDX, m_NrOfRW, 2, 1024);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPvrHDDBenchDlg, CDialog)
//{{AFX_MSG_MAP(CPvrHDDBenchDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_NOTIFY(NM_DBLCLK, IDC_HDDLIST, OnDblclkHddlist)
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_BUTTON1, OnBenchmark)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPvrHDDBenchDlg message handlers
BOOL CPvrHDDBenchDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
FindSystemDrives();
// init interface values
// let's take care of sliders
UpdateData(TRUE);
m_StrCurDrive.Format("NO DRIVE SELECTED");
UpdateData(FALSE);
// init interface values
return TRUE; // return TRUE unless you set the focus to a control
}
void CPvrHDDBenchDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CPvrHDDBenchDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CPvrHDDBenchDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void
CPvrHDDBenchDlg::FindSystemDrives()
{
CString StrDriveName;
short DriveNumber;
HANDLE hDrive;
// try to find physical drive 0 (should exist !!!)
DriveNumber = 0;
StrDriveName.Format("\\\\.\\PHYSICALDRIVE%d",DriveNumber);
hDrive = CreateFile(StrDriveName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
while(hDrive != INVALID_HANDLE_VALUE)
{
CloseHandle(hDrive);
m_HDDList.InsertItem(DriveNumber,StrDriveName);
// try to find another physical drive
DriveNumber++;
StrDriveName.Format("\\\\.\\PHYSICALDRIVE%d",DriveNumber);
hDrive = CreateFile(StrDriveName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
}
CloseHandle(hDrive);
}
void CPvrHDDBenchDlg::OnDblclkHddlist(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
// make this disk the current benchmarked disk
CListCtrl* pList = (CListCtrl*) GetDlgItem(pNMHDR->idFrom);
POSITION pos = pList->GetFirstSelectedItemPosition();
if(pos)
{
// find the selected HDD
int nItem = pList->GetNextSelectedItem(pos);
if(nItem==0) return; // do not allow to choose physical drive 0
m_CurHDD = (SHORT) nItem;
UpdateBenchDrive();
UpdateBenchParams();
}
}
void CPvrHDDBenchDlg::UpdateBenchDrive()
{
CString StrDriveName;
DISK_GEOMETRY geometry;
DWORD breturn;
if(m_hSelectedDrive != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hSelectedDrive);
m_hSelectedDrive = INVALID_HANDLE_VALUE;
}
StrDriveName.Format("\\\\.\\PHYSICALDRIVE%d",m_CurHDD);
m_hSelectedDrive = CreateFile(StrDriveName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
// get information about drive geometry :)
DeviceIoControl(m_hSelectedDrive,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&geometry,sizeof(DISK_GEOMETRY),&breturn,NULL);
// we need to have the drive size !
m_DriveSize = geometry.Cylinders.QuadPart*geometry.TracksPerCylinder*geometry.SectorsPerTrack*geometry.BytesPerSector;
UpdateData(TRUE);
m_StrCurDrive.Format("%s IS SELECTED [ %I64u cyl | %Lu tracks/cyl | %Lu sec/track | %Lu bytes/sec | %.2f GBytes ]" , StrDriveName,
geometry.Cylinders.QuadPart,
geometry.TracksPerCylinder,
geometry.SectorsPerTrack,
geometry.BytesPerSector,
(float)m_DriveSize/(1024*1024*1024));
UpdateData(FALSE);
}
void CPvrHDDBenchDlg::UpdateBenchParams()
{
}
void CPvrHDDBenchDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
}
#define SET_XY_READ(i,xv,yv) index[0]=i;index[1]=0;saResults.PutElement(index,COleVariant(xv));\
index[0]=i;index[1]=1;saResults.PutElement(index,COleVariant(yv));
#define SET_XY_WRITE(i,xv,yv) index[0]=i;index[1]=2;saResults.PutElement(index,COleVariant(xv));\
index[0]=i;index[1]=3;saResults.PutElement(index,COleVariant(yv));
void CPvrHDDBenchDlg::OnBenchmark()
{
DWORD CurrentCtlPoint;
DWORD CurrentRW;
DWORD BytesRead;
DWORD BytesWritten;
LONG OffsetLow;
LONG OffsetHigh;
__int64 CurrentReadOffset,CurrentWriteOffset;
__int64 CurrentReadBaseOffset,CurrentWriteBaseOffset;
__int64 CtlPointDistance;
UCHAR *pReadBuffer;
UCHAR *pWriteBuffer;
//// Update the data, so that we have the current values
UpdateData(TRUE);
UpdateData(FALSE);
////
COleSafeArray saResults;
DWORD nElts[2];
long index[2];
double readrate,writerate;
double readbase,writebase;
double time;
CtlPointDistance = m_BlkSize * m_NrOfRW * 1024;
m_NrofControlPoints = m_DriveSize/CtlPointDistance;
m_Progress.SetRange32(0,m_NrofControlPoints);
m_Progress.SetPos(0);
pReadBuffer = new UCHAR[1024*m_BlkSize];
pWriteBuffer = new UCHAR[1024*m_BlkSize];
QueryPerformanceFrequency(&m_CounterFrequency);
// create the safearray that will hold the datas
nElts[0] = m_NrofControlPoints;
nElts[1] = 4;
saResults.Create(VT_VARIANT,2,nElts);
for(CurrentCtlPoint=0;CurrentCtlPoint<m_NrofControlPoints;CurrentCtlPoint++)
{
CurrentReadBaseOffset = CurrentCtlPoint * CtlPointDistance;
CurrentWriteBaseOffset = (m_NrofControlPoints-CurrentCtlPoint-1)*CtlPointDistance;
CurrentReadOffset = CurrentReadBaseOffset;
CurrentWriteOffset = CurrentWriteBaseOffset;
for(CurrentRW=0;CurrentRW<m_NrOfRW;CurrentRW++)
{
// Read Operation
if(!CurrentRW) QueryPerformanceCounter(&m_ReadStartTime); // start the counter
OffsetHigh = (LONG)(CurrentReadOffset >> 32);
OffsetLow = (LONG)(CurrentReadOffset & 0x00000000FFFFFFFF);
SetFilePointer(m_hSelectedDrive,OffsetLow,&OffsetHigh,FILE_BEGIN);
ReadFile(m_hSelectedDrive,pReadBuffer,1024*m_BlkSize,&BytesRead,NULL);
if(CurrentRW == (m_NrOfRW-1))
QueryPerformanceCounter(&m_ReadStopTime); // stop the counter
// Write Operation
if(!CurrentRW) QueryPerformanceCounter(&m_WriteStartTime); // start the counter
OffsetHigh = (LONG)(CurrentWriteOffset >> 32);
OffsetLow = (LONG)(CurrentWriteOffset & 0x00000000FFFFFFFF);
SetFilePointer(m_hSelectedDrive,OffsetLow,&OffsetHigh,FILE_BEGIN);
WriteFile(m_hSelectedDrive,pWriteBuffer,1024*m_BlkSize,&BytesWritten,NULL);
CurrentReadOffset += (1024*m_BlkSize);
CurrentWriteOffset += (1024*m_BlkSize);
}
QueryPerformanceCounter(&m_WriteStopTime); // stop the counter
time = (double)(m_WriteStopTime.QuadPart - m_WriteStartTime.QuadPart)/m_CounterFrequency.QuadPart;
writerate = (double)(m_BlkSize*m_NrOfRW)/(1024*time);
time = (double)(m_ReadStopTime.QuadPart - m_ReadStartTime.QuadPart)/m_CounterFrequency.QuadPart;
readrate = (double)(m_BlkSize*m_NrOfRW)/(1024*time);
readbase = (double)(CurrentReadBaseOffset + (double)CtlPointDistance/2)/(1024*1024*1024);
writebase = (double)(CurrentWriteBaseOffset + (double)CtlPointDistance/2)/(1024*1024*1024);
SET_XY_READ(CurrentCtlPoint,readbase,(double)readrate);
SET_XY_WRITE(CurrentCtlPoint,writebase,(double)writerate);
m_Progress.SetPos(CurrentCtlPoint);
}
delete pReadBuffer;
delete pWriteBuffer;
// just make sure the graph looks 'good' !!
VARIANT idx;
CVcPlot plot = m_Chart.GetPlot();
plot.SetAutoLayout(FALSE);
idx.decVal.sign = 1;
CVcAxis xaxis = plot.GetAxis(0,idx);
CVcValueScale xvscale = xaxis.GetValueScale();
plot.SetUniformAxis(FALSE);
xvscale.SetAuto(FALSE);
xvscale.SetMinimum(0.0);
xvscale.SetMaximum((double)m_DriveSize/(1024*1024*1024));
//
m_Chart.SetChartData(saResults.Detach());
m_Chart.SetColumnCount(4);
m_Chart.SetRowCount((short)m_NrofControlPoints);
m_Chart.SetColumn(1);m_Chart.SetColumnLabel("READ");
m_Chart.SetColumn(3);m_Chart.SetColumnLabel("WRITE");
m_Chart.Refresh();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -