I'm converting a Delphi app to C#. One part of the program requires writing many packed records
in Delphi, or structs
in C#, to a binary file. These files are around 400mb. The Delphi
version I have completes writing to the file around 8 seconds
, whereas the C#
version takes around 800 seconds
. What could I do to improve speed in the C# version?
Here's the Delphi version:
CONST
RecordSize= 128;
HeaderSize=128;
TESTrec = packed record
now: TDateTime;
//other fields here
end;
TESThdrrec = packed record
now: TDateTime;
Firsttime: TDateTime;
Lasttime: TDateTime;
//other fields listed here
end;
Function TRampBuildForm.CreateTest(FilePath:String;StartTime:TDateTime;EndTime:TDateTime):Boolean;
var
Records:Int64;
CurrentOffSet:Int64;
CurrentTime:TDateTime;
NewRec:TESTrec;
NewHeader:TESThdrrec;
ix:Integer;
percent:Integer;
begin
Try
RampStream:=TFileStream.Create(FilePath,fmCreate OR fmShareExclusive );
except
ShowMessage('cannot create Ramp '+Rampname+chr(13)+'Check to see if file is open');
CreateTest:=false;
end;
FillChar(NewHeader,HeaderSize,0);
NewHeader.now:=Now;
NewHeader.Firsttime:=StartTime;
NewHeader.LastTime:= EndTime;
FirstAllowableTime:=StartTime;
LastAllowableTime:=EndTime;
Records:= Round((EndTime-StartTime)/ONE_SECOND)+1;
RampStream.Write(NewHeader,HeaderSize);
FillChar(NewRec,RecordSize,0);
label8.Caption:='Expanding ';
Progressbar1.Position:=0;
CurrentTime:=StartTime;
percent:=0;
refresh;
Application.ProcessMessages;
For ix:= 1 to Records do
begin
if (ix*100) div Records > percent then
begin
percent:= (ix*100) div Records;
Progressbar1.position:=percent;
refresh;
Application.ProcessMessages
end;
NewRec.Now:=CurrentTime;
RampStream.Write(NewRec,RecordSize);
CurrentTime:=CurrentTime + ONE_SECOND;
end;
ProgressBar1.Position:=100;
refresh;
CreateTest:=True;
RampStream.Free;
end;
My C# version:
const int RecordSize = 128;
const int HeaderSize = 128;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Testrec
{
public double now;
//other fields here
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TESThdrrec
{
public double now;
public double Firsttime;
public double Lasttime;
//other fields here
}
private Boolean CreateTest(string FilePath, double StartTime, double EndTime)
{
long Records;
long CurrentOffSet;
double CurrentTime;
TESTrec NewRec = new TESTrec();
TESThdrrec NewHeader = new TESThdrrec();
int ix;
int percent;
NewHeader.now = System.DateTime.Now.ToOADate();
NewHeader.Firsttime = StartTime;
NewHeader.Lasttime = EndTime;
FirstAllowableTime = StartTime;
LastAllowableTime = EndTime;
if (!File.Exists(FilePath)) //if file doesn't exist
{
try
{
using (RampStream = new FileStream(FilePath, FileMode.Create))
{
byte[] buffer = GetBytes2(NewHeader); //puts struct into byte array
RampStream.Write(buffer, 0, HeaderSize); //write byte array to file
}
}
catch (Exception e)
{
System.Windows.MessageBox.Show("Cannot create file" + RampName + Environment.NewLine + "Error Message: " + e);
}
}
Records = (long)(Math.Round((EndTime - StartTime) / ONE_SECOND) + 1);
RampInfo.Content = "Expanding ";
ProgressBar1.Value = 0;
CurrentTime = StartTime;
percent = 0;
//TAKING LONG TIME HERE!!
for (ix = 1; ix <= Records; ix++)
{
if (((ix * 100) / Records) > percent)
{
percent = (ix * 100) / (int)Records;
}
NewRec.now = CurrentTime;
using (RampStream = new FileStream(FilePath, FileMode.Open))
{
byte[] buffer = GetBytes2(NewRec); //puts struct into byte array
RampStream.Write(buffer, 0, RecordSize); //write byte array to file
}
//RampStream.Write(NewRec, RecordSize);
CurrentTime = CurrentTime + ONE_SECOND;
}
ProgressBar1.Value = 100;
RampStream.Close();
return true;
}
There is a progress bar being updated in the for loop
, which is where the code is getting hung up on. I'm not refreshing it or using the FillChar
equivalent that the Delphi version is using, but I don't think that would impact this?
You are opening and closing the stream for every write! Open the file once at the start of the writing loop, and close it at the end of the loop (like you do in the old code).
(You'll want to make sure you are still using a using
statement to close the file.)