Link to home
Start Free TrialLog in
Avatar of charles_gilley
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::DumpFaultDataToFile(CStringList *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_LOG_FILE,
      if (!dumpFile.Open(_T("\\Windows\\FaultLog.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\nChannel %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();
      }

}
Avatar of charles_gilley
charles_gilley

ASKER

Addendum: I'm using Windows CE 4.1, x86 target.
ASKER CERTIFIED SOLUTION
Avatar of chensu
chensu
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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