#1 Re: Low level and performance » Dictionary type » 2011-03-19 20:46:29

Starkis wrote:

Delphi 7 doesn't have dictionary type collection - maybe there are custom units for that? generics also are not available for the D7 sad

found:
- delphi collections (http://www.warmachine.u-net.com/delphi_collections/)
- decal (http://sourceforge.net/projects/decal/)
and several variations, but users complain about poor performance :-/

I like RBS AntiDOT library

#2 Re: Low level and performance » Very fast asm-implementation of Base64 Encoding/Decoding » 2011-03-19 20:37:35

Arnaud, you're the best. cool

ab wrote:

Should be faster than the one you quoted...

Unfortunately, on my very old PC (Intel Pentium 4 Prescott, 2800 MHz) I took these results (Delphi XE): sad

Starting benchmarks on 2 cores.
SynCommons.BinToBase64                   took     0,598192519 sec.
SynCommons.Base64ToBin                   took     0,563155921 sec.
BASE64Codec.Base64Encode function        took     0,724407766 sec.
BASE64Codec.Base64Decode function        took     0,657267154 sec.
BASE64Codec.Base64Decode procedure       took     0,401618684 sec.
BASE64Codec.Base64Decode procedure       took     0,338995311 sec.
All benchmarks passed.

My benchmark program:

program BASE64_Benchmarks;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils, Benchmarker, BASE64Codec, SynCommons;

procedure RunBenchmarks;

var
  b: TBenchmarker;

  OriginalRawS,
  EncodedRawS, DecodedRawS: RawByteString;

  OriginalAnsiS,
  EncodedAnsiS, DecodedAnsiS: AnsiString;

begin
  b := TBenchmarker.Create(procedure(Name: string; Time: Double)
                           begin
                             WriteLn(Format('%-40s took %15.9f sec.', [Name, Time * 1000000]));
                           end);

  try
    b.Warmups := 100;
    b.Iterations := 1000000;

    OriginalRawS := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    OriginalAnsiS := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    EncodedRawS := '';
    b.Benchmark('SynCommons.BinToBase64',
                procedure
                begin
                  EncodedRawS := SynCommons.BinToBase64(OriginalRawS);
                end);

    DecodedRawS := '';

    b.Benchmark('SynCommons.Base64ToBin',
                procedure
                begin
                  DecodedRawS := SynCommons.Base64ToBin(EncodedRawS);
                end);
    Assert(DecodedRawS = OriginalRawS);

    EncodedAnsiS := '';

    b.Benchmark('BASE64Codec.Base64Encode function',
                procedure
                begin
                  EncodedAnsiS := BASE64Codec.Base64Encode(OriginalAnsiS);
                end);

    DecodedAnsiS := '';

    b.Benchmark('BASE64Codec.Base64Decode function',
                procedure
                begin
                  DecodedAnsiS := BASE64Codec.Base64Decode(EncodedAnsiS);
                end);
    Assert(DecodedAnsiS = OriginalAnsiS);

    EncodedAnsiS := '';

    b.Benchmark('BASE64Codec.Base64Decode procedure',
                procedure
                begin
                  BASE64Codec.Base64Encode(OriginalAnsiS, EncodedAnsiS);
                end);

    DecodedAnsiS := '';

    b.Benchmark('BASE64Codec.Base64Decode procedure',
                procedure
                begin
                  BASE64Codec.Base64Decode(EncodedAnsiS, DecodedAnsiS);
                end);
    Assert(DecodedAnsiS = OriginalAnsiS);

  finally
  end;
end;

procedure SetAtMaxSpeed;
var
  SysInfo: _SYSTEM_INFO;
begin
  SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS);
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_HIGHEST);
  GetSystemInfo(SysInfo);
  WriteLn('Starting benchmarks on ', SysInfo.dwNumberOfProcessors, ' cores.');
  if SysInfo.dwNumberOfProcessors > 1 then
  begin
    SetThreadAffinityMask(GetCurrentThread, 1 shl (SysInfo.dwNumberOfProcessors - 1));
    SetProcessAffinityMask(GetCurrentProcess, 1 shl (SysInfo.dwNumberOfProcessors - 1));
  end;
end;

begin
  try
    SetAtMaxSpeed;
    RunBenchmarks;
    WriteLn('All benchmarks passed.')
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

IMHO, very cool benchmarker:

unit Benchmarker;

interface

uses
  SysUtils;

type
  // TBenchmarker "stolen" from Barry Kelly -- http://barrkel.blogspot.com/2008/08/anonymous-methods-in-testing-profiling.html
  TBenchmarker = record
  private
    const
      DefaultIterations = 3;
      DefaultWarmups = 1;
    var
      FReportSink: TProc<string, Double>;
      FWarmups: Integer;
      FIterations: Integer;
      FOverhead: Double;
    class var
      FFreq: Int64;
    class procedure InitFreq; static;
  public
    constructor Create(const AReportSink: TProc<string, Double>);

    class function Benchmark(const Code: TProc;
                             Iterations: Integer = DefaultIterations;
                             Warmups: Integer = DefaultWarmups): Double; overload; static;

    procedure Benchmark(const Name: string; const Code: TProc); overload;
    function Benchmark<T>(const Name: string; const Code: TFunc<T>): T; overload;

    property Warmups: Integer read FWarmups write FWarmups;
    property Iterations: Integer read FIterations write FIterations;
  end;

implementation

uses
  Windows;

{ TBenchmarker }

constructor TBenchmarker.Create(const AReportSink: TProc<string, Double>);
begin
  InitFreq;
  FReportSink := AReportSink;
  FWarmups := DefaultWarmups;
  FIterations := DefaultIterations;

  // Estimate overhead of harness
  FOverhead := Benchmark(procedure begin end, 100, 3);
end;

class procedure TBenchmarker.InitFreq;
begin
  if (FFreq = 0) and not QueryPerformanceFrequency(FFreq) then
    raise Exception.Create('No high-performance counter available.');
end;

procedure TBenchmarker.Benchmark(const Name: string; const Code: TProc);
begin
  FReportSink(Name, Benchmark(Code, Iterations, Warmups) - FOverhead);
end;

class function TBenchmarker.Benchmark(const Code: TProc; Iterations, Warmups: Integer): Double;
var
  start, stop: Int64;
  i: Integer;
begin
  InitFreq;

  for i := 1 to Warmups do
    Code;

  QueryPerformanceCounter(start);
  for i := 1 to Iterations do
    Code;
  QueryPerformanceCounter(stop);

  Result := (stop - start) / FFreq / Iterations;
end;

function TBenchmarker.Benchmark<T>(const Name: string; const Code: TFunc<T>): T;
var
  start, stop: Int64;
  i: Integer;
begin
  for i := 1 to FWarmups do
    Result := Code;

  QueryPerformanceCounter(start);
  for i := 1 to FIterations do
    Result := Code;
  QueryPerformanceCounter(stop);

  FReportSink(Name, (stop - start) / FFreq / Iterations - FOverhead);
end;

end.

Maybe, these strange results because var parameters used ?

ab wrote:

Thanks for pushing me to write faster code. wink

I've many useful links. So, periodically, I'll distract your from hard work.  smile
With your permission, by your leave, of course.

#4 Re: Low level and performance » Fastest CRC calculation » 2010-08-08 19:51:50

Oh no, this code is not mine!
I just use it and I'm not so well know asm smile

And Aleksandr has repeatedly was on the Fastcode Winner's List.

ab wrote:

You should make some blog or web site to publish code like this.

This code has already been published, but only on the Russian Delphi forum.

#5 Low level and performance » Fastest CRC calculation » 2010-08-08 13:27:49

dataman
Replies: 8

Hello!
Thank you for very interesting projects!

Offer your attention units with fastest parallel calculation CRC: CRC32 & CRC64
These modules created by Aleksandr Sharahov.

P.S. Sorry for bad english.

Board footer

Powered by FluxBB