charles_gilley
asked on
How to improve CStdioFile / CFile performance in WinCE?
My application has the requirement to dump memory to a file on command. This file is about 500K.
It's taking me upwards of 4 minutes to complete the task. Initially, the file location was on the "harddrive" -
the compact flash for this device. I moved the file location to the ram disk area - it writes in about 3 seconds.
I then go into Windows Explorer, copy the file from the ram disk to the compact flash - and it takes 3 seconds
to copy. This tells me that I can write to the compact flash just as fast as the copy command. So, what the
heck is wrong with the code below. To summarize what the code is doing, we have some preformatted
information going to the text dump and then unformatted binary data that I expand out 8 longwords per row.
Nothing complex.
Thanks for taking a look. I'm at the point now to just write to RAM and then copy the file, but this
approach maxes out my tackiness meter.
void CFaultStackPopupDlg::DumpF aultDataTo File(CStri ngList *pMsgList, FAULT_STACK_TYPE *pFS)
{
int i;
CNLangString sText;
CString sDebugText;
char szFileTxt[1024];
CFile dumpFile;
CFileException ex;
// Open the file in truncate mode. There is one and only one text dump. There may be
// binary dumps later.
//if (!dumpFile.Open(N_FAULT_LO G_FILE,
if (!dumpFile.Open(_T("\\Wind ows\\Fault Log.txt"),
CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone | CFile::typeBinary, &ex))
{
#ifdef _DEBUG
// Complain if an error happened.
// There is no reason to delete the ex object.
TCHAR szError[1024];
ex.GetErrorMessage(szError , 1024);
afxDump << szError << _T(" (") << ex.m_cause << ")\n";
#endif
}
else
{
// Extend the file to something approximating the actual file dump. This works out to be about
// 500K.
long dwSize = 500000;
dumpFile.SetLength(dwSize) ;
// Prefix the dump with the current date and time (according to the ENGINE!).
TIME_TYPE et = m_pNMS->get_Time(0);
CString sText;
sText.Format(_T("\r\nFault stack dump on %02.2d/%02.2d/%02.2d %2.2d:%2.2d:%2.2d\r\n\r\n" ),
et.Day, et.Month, et.Year, et.Hour, et.Minute, et.Second);
// Convert string from Unicode (16-bit) to 8-bit - so you can read what is in the log file.
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
// Append line to file.
dumpFile.SeekToBegin();
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// Now dump the fault stack.
POSITION pos = pMsgList->GetHeadPosition( );
for (i = 0; i < pMsgList->GetCount(); i++)
{
sText = pMsgList->GetNext(pos);
sText += _T("\r\n");
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
// Now that the preamble is complete, dump the stack data and then the channel data.
// Format is "xx 0x00000000..." where xx is the address in hex, followed by 8 longwords of data.
sText = _T("\r\n\r\nStack Dump\r\n");
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
for (i = 0; i < 50/8; i++) // first full 6
{
sText.Format(_T("%2.2x 0x%8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\r\n"),
i * 8,
pFS->StackSpace[i + 0],
pFS->StackSpace[i + 1],
pFS->StackSpace[i + 2],
pFS->StackSpace[i + 3],
pFS->StackSpace[i + 4],
pFS->StackSpace[i + 5],
pFS->StackSpace[i + 6],
pFS->StackSpace[i + 7]);
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
// Last 2.
sText.Format(_T("%2.2x 0x%8.8x %8.8x\r\n"),
48,
pFS->StackSpace[i + 0],
pFS->StackSpace[i + 1]);
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// Now dump the channel data. This comes in 24 sets of 2000 long words.
// Same code as above.
for (int nChannel = 0; nChannel < 24; nChannel++)
{
sText.Format(_T("\r\n\r\nC hannel %d Data:\r\n\r\n"), nChannel);
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// dump this channel's data. 2K longwords == 250 rows @ 8 lw/row.
for (i = 0; i < 2000/8; i++)
{
sText.Format(_T("%3.3x 0x%8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\r\n"),
i * 8,
pFS->Channel[nChannel][i + 0],
pFS->Channel[nChannel][i + 1],
pFS->Channel[nChannel][i + 2],
pFS->Channel[nChannel][i + 3],
pFS->Channel[nChannel][i + 4],
pFS->Channel[nChannel][i + 5],
pFS->Channel[nChannel][i + 6],
pFS->Channel[nChannel][i + 7]);
WideCharToMultiByte(CP_ACP , 0, sText, -1, szFileTxt, 1024, NULL, NULL);
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
}
dumpFile.Close();
}
}
It's taking me upwards of 4 minutes to complete the task. Initially, the file location was on the "harddrive" -
the compact flash for this device. I moved the file location to the ram disk area - it writes in about 3 seconds.
I then go into Windows Explorer, copy the file from the ram disk to the compact flash - and it takes 3 seconds
to copy. This tells me that I can write to the compact flash just as fast as the copy command. So, what the
heck is wrong with the code below. To summarize what the code is doing, we have some preformatted
information going to the text dump and then unformatted binary data that I expand out 8 longwords per row.
Nothing complex.
Thanks for taking a look. I'm at the point now to just write to RAM and then copy the file, but this
approach maxes out my tackiness meter.
void CFaultStackPopupDlg::DumpF
{
int i;
CNLangString sText;
CString sDebugText;
char szFileTxt[1024];
CFile dumpFile;
CFileException ex;
// Open the file in truncate mode. There is one and only one text dump. There may be
// binary dumps later.
//if (!dumpFile.Open(N_FAULT_LO
if (!dumpFile.Open(_T("\\Wind
CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone | CFile::typeBinary, &ex))
{
#ifdef _DEBUG
// Complain if an error happened.
// There is no reason to delete the ex object.
TCHAR szError[1024];
ex.GetErrorMessage(szError
afxDump << szError << _T(" (") << ex.m_cause << ")\n";
#endif
}
else
{
// Extend the file to something approximating the actual file dump. This works out to be about
// 500K.
long dwSize = 500000;
dumpFile.SetLength(dwSize)
// Prefix the dump with the current date and time (according to the ENGINE!).
TIME_TYPE et = m_pNMS->get_Time(0);
CString sText;
sText.Format(_T("\r\nFault
et.Day, et.Month, et.Year, et.Hour, et.Minute, et.Second);
// Convert string from Unicode (16-bit) to 8-bit - so you can read what is in the log file.
WideCharToMultiByte(CP_ACP
// Append line to file.
dumpFile.SeekToBegin();
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// Now dump the fault stack.
POSITION pos = pMsgList->GetHeadPosition(
for (i = 0; i < pMsgList->GetCount(); i++)
{
sText = pMsgList->GetNext(pos);
sText += _T("\r\n");
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
// Now that the preamble is complete, dump the stack data and then the channel data.
// Format is "xx 0x00000000..." where xx is the address in hex, followed by 8 longwords of data.
sText = _T("\r\n\r\nStack Dump\r\n");
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
for (i = 0; i < 50/8; i++) // first full 6
{
sText.Format(_T("%2.2x 0x%8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\r\n"),
i * 8,
pFS->StackSpace[i + 0],
pFS->StackSpace[i + 1],
pFS->StackSpace[i + 2],
pFS->StackSpace[i + 3],
pFS->StackSpace[i + 4],
pFS->StackSpace[i + 5],
pFS->StackSpace[i + 6],
pFS->StackSpace[i + 7]);
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
// Last 2.
sText.Format(_T("%2.2x 0x%8.8x %8.8x\r\n"),
48,
pFS->StackSpace[i + 0],
pFS->StackSpace[i + 1]);
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// Now dump the channel data. This comes in 24 sets of 2000 long words.
// Same code as above.
for (int nChannel = 0; nChannel < 24; nChannel++)
{
sText.Format(_T("\r\n\r\nC
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
// dump this channel's data. 2K longwords == 250 rows @ 8 lw/row.
for (i = 0; i < 2000/8; i++)
{
sText.Format(_T("%3.3x 0x%8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\r\n"),
i * 8,
pFS->Channel[nChannel][i + 0],
pFS->Channel[nChannel][i + 1],
pFS->Channel[nChannel][i + 2],
pFS->Channel[nChannel][i + 3],
pFS->Channel[nChannel][i + 4],
pFS->Channel[nChannel][i + 5],
pFS->Channel[nChannel][i + 6],
pFS->Channel[nChannel][i + 7]);
WideCharToMultiByte(CP_ACP
dumpFile.Write(szFileTxt, strlen(szFileTxt));
}
}
dumpFile.Close();
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Chensu,
Thank you very much for the pointers. The CMemFile helped me out immensely as I really did not want to add yet more memory mgt. to an otherwise simple operation.
chg
Thank you very much for the pointers. The CMemFile helped me out immensely as I really did not want to add yet more memory mgt. to an otherwise simple operation.
chg
ASKER