The Embarcadero official said "TFDMemTable is faster than TClientDataSet",But I Make an little speed test and TFDMemtable slower than TClientDataset (Delphi XE7).
{
Test 30k records
TClientDataSet TFDMemTable
Append 1482ms 2153ms
SaveToFile 125ms 348ms
SaveToStream 125ms 312ms
LoadFromFile 109ms 686ms
LoadFromStream 234ms 718ms
}
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error,
FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Comp.DataSet, FireDAC.Comp.Client, Data.DB,
Datasnap.DBClient, Vcl.StdCtrls, Vcl.Samples.Spin, FireDAC.Stan.StorageBin;
type
TForm1 = class(TForm)
btnFDAppend: TButton;
btnAppend: TButton;
seCount: TSpinEdit;
btnFDEmptyDataSet: TButton;
btnEmptyDataSet: TButton;
lblClientDataset: TLabel;
lblFDMemTable: TLabel;
btnSaveToFile: TButton;
btnFDSaveToFile: TButton;
btnLoadFromFile: TButton;
btnFDLoadFromFile: TButton;
btnSaveToStream: TButton;
btnFDSaveToStream: TButton;
btnFDLoadFromStream: TButton;
btnLoadFromStream: TButton;
lblRecordCount: TLabel;
lblWhy: TLabel;
procedure FormCreate(Sender: TObject);
procedure btnFDAppendClick(Sender: TObject);
procedure btnAppendClick(Sender: TObject);
procedure btnFDEmptyDataSetClick(Sender: TObject);
procedure btnLoadFromFileClick(Sender: TObject);
procedure btnSaveToFileClick(Sender: TObject);
procedure btnFDSaveToFileClick(Sender: TObject);
procedure btnFDLoadFromFileClick(Sender: TObject);
procedure btnSaveToStreamClick(Sender: TObject);
procedure btnFDSaveToStreamClick(Sender: TObject);
procedure btnLoadFromStreamClick(Sender: TObject);
procedure btnFDLoadFromStreamClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnEmptyDataSetClick(Sender: TObject);
private
FStartTime: DWORD;
FFDStream, FCDSStream: TMemoryStream;
FClientDataSet: TClientDataSet;
FFDMemTable: TFDMemTable;
function NewFDMemTable: TFDMemTable;
function NewClientDataSet: TClientDataSet;
procedure ShowDuration(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnFDAppendClick(Sender: TObject);
var
I: Integer;
begin
FStartTime := GetTickCount;
FFDMemTable.DisableControls;
try
for I := 1 to seCount.Value do
begin
FFDMemTable.Append;
FFDMemTable.FieldByName('ID').AsInteger := I;
FFDMemTable.FieldByName('Status').AsString := 'Code' + IntToStr(i);
FFDMemTable.FieldByName('Created').AsDateTime := Date();
FFDMemTable.FieldByName('Volume').AsFloat := Random(10000);
FFDMemTable.Post;
end;
finally
FFDMemTable.EnableControls;
end;
ShowDuration(Sender);
end;
procedure TForm1.btnLoadFromFileClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FClientDataSet.LoadFromFile('CDS.dat');
ShowDuration(Sender);
end;
procedure TForm1.btnSaveToFileClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FClientDataSet.SaveToFile('CDS.dat', dfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnFDEmptyDataSetClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FFDMemTable.EmptyDataSet;
ShowDuration(Sender);
end;
procedure TForm1.btnEmptyDataSetClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FClientDataSet.EmptyDataSet;
ShowDuration(Sender);
end;
procedure TForm1.btnFDSaveToFileClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FFDMemTable.SaveToFile('FD.dat', sfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnSaveToStreamClick(Sender: TObject);
begin
FCDSStream.Clear;
FStartTime := GetTickCount;
FClientDataSet.SaveToStream(FCDSStream, dfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnFDLoadFromFileClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FFDMemTable.LoadFromFile('FD.dat', sfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnFDSaveToStreamClick(Sender: TObject);
begin
FFDStream.Clear;
FStartTime := GetTickCount;
FFDMemTable.SaveToStream(FFDStream, sfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnFDLoadFromStreamClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FFDStream.Position := 0;
FFDMemTable.LoadFromStream(FFDStream, sfBinary);
ShowDuration(Sender);
end;
procedure TForm1.btnLoadFromStreamClick(Sender: TObject);
begin
FStartTime := GetTickCount;
FCDSStream.Position := 0;
FClientDataSet.LoadFromStream(FCDSStream);
ShowDuration(Sender);
end;
procedure TForm1.btnAppendClick(Sender: TObject);
var
I: Integer;
begin
FStartTime := GetTickCount;
FClientDataSet.DisableControls;
try
for I := 1 to seCount.Value do
begin
FClientDataSet.Append;
FClientDataSet.FieldByName('ID').AsInteger := I;
FClientDataSet.FieldByName('Status').AsString := 'Code' + I.ToString;
FClientDataSet.FieldByName('Created').AsDateTime := Date();
FClientDataSet.FieldByName('Volume').AsFloat := Random(10000);
FClientDataSet.Post;
end;
finally
FClientDataSet.EnableControls;
end;
ShowDuration(Sender);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FFDMemTable := NewFDMemTable;
// FFDMemTable.FormatOptions.InlineDataSize := 10;
FClientDataSet := NewClientDataSet;
FCDSStream := TMemoryStream.Create;
FFDStream := TMemoryStream.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(FFDMemTable);
FreeAndNil(FClientDataSet);
FreeAndNil(FCDSStream);
FreeAndNil(FFDStream);
end;
function TForm1.NewClientDataSet: TClientDataSet;
begin
Result := TClientDataSet.Create(nil);
with Result do
begin
FieldDefs.Add('ID', ftInteger, 0, False);
FieldDefs.Add('Status', ftString, 10, False);
FieldDefs.Add('Created', ftDate, 0, False);
FieldDefs.Add('Volume', ftFloat, 0, False);
CreateDataSet;
LogChanges := False;
end;
end;
function TForm1.NewFDMemTable: TFDMemTable;
begin
Result := TFDMemTable.Create(nil);
with Result do
begin
FieldDefs.Add('ID', ftInteger, 0, False);
FieldDefs.Add('Status', ftString, 10, False);
FieldDefs.Add('Created', ftDate, 0, False);
FieldDefs.Add('Volume', ftFloat, 0, False);
CreateDataSet;
LogChanges := False;
end;
end;
procedure TForm1.ShowDuration(Sender: TObject);
var
s: string;
idx: Integer;
begin
s := TButton(Sender).Caption;
idx := s.IndexOf('-');
if idx > 0 then
s := s.Substring(0, idx);
TButton(Sender).Caption := Format('%s-%dms', [s, (GetTickCount - FStartTime)]);
end;
end.
This is test result screenshot:
This is the test application source.