【Delphi】使用并行数组和有序字典加快 Delphi RTL 速度(D12.2)

Delphi 12.2新增功能比较多,但 Delphi 运行时库(RTL)中的一些增强功能值得一提。比如:

新 TParallelArray 类

        System.Threading 单元中有一个新的 TParallelArray 类,可以在数组项上并行运行 &For 和排序等操作。 在多核系统中,这可以大大提高运行速度。 如何使用? 这是一个简单的测试用例、命令行项目,它创建了两个完全相同的数组,并使用常规的单线程排序和新的并行版本进行排序:

program ParallelArray;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections,
  System.Threading,
  System.Diagnostics;

var
  A1, A2: array of Integer;
  I: Integer;
  T: TStopwatch;

begin
  try
    SetLength(A1, 100_000_000);
    SetLength(A2, 100_000_000);
    for I := 0 to High(A1) do
    begin
      A1[I] := Random(MaxInt);
      A2[I] := A1[I];
    end;

    // Warm up thread pool
    TTask.Create(
      procedure
      begin
        // empty
      end).Start;

    // Serial sorting
    T := TStopwatch.StartNew;
    TArray.Sort<Integer>(A1);
    T.Stop;
    Writeln('TArray.Sort: ', T.Elapsed.ToString);

    // Parallel sorting
    T := TStopwatch.StartNew;
    TParallelArray.Sort<Integer>(A2);
    T.Stop;
    Writeln('TParallelArray.Sort: ', T.Elapsed.ToString);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

如果在我的主电脑(英特尔(R)酷睿(TM)i7-10700 处理器,主频为 2.90GHz )上运行它,会得到以下结果,性能提高了 585%! (为便于阅读,输出结果已缩减为毫秒级)

TArray.Sort: 00:00:16.414
TParallelArray.Sort: 00:00:02.889

新的 TOrderedDictionary 类

        System.Generics.Collections 单元中还有一个从 TDictionary<K,V> 派生的新 TOrderedDictionary 类。 有序字典是在字典中集成了排序方法的字典。 这使得 for in 循环以排序顺序浏览数据变得简单,也使查找元素变得更快。 举例来说,请看下面的项目:

  • 创建一个有序字典并添加一些元素
  • 显示输出结果以及查找一个键 1 亿次所需的时间
  • 按键排序,再次显示输出结果并重复 1 亿次查找调用(快得多!)
  • 按值排序,再次显示
  • 添加一个额外的元素,以证明元素不会随排序顺序添加,您需要根据需要进行调整(插入多个元素时,这种方法通常更快)。
program OrderedDictionaryDemo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Generics.Collections,
  System.Diagnostics;

var
  T: TStopwatch;

begin
  try
    var ODict := TOrderedDictionary <string, string>.Create;
    ODict.Add ('one', 'London');
    ODict.Add ('two', 'Berlin');
    ODict.Add ('three', 'Rome');
    ODict.Add ('four', 'Athens');
    ODict.Add ('five', 'Madrid');
    ODict.Add ('six', 'Bruxelles');
    ODict.Add ('seven', 'Paris');

    writeln ('Natural');
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    T := TStopwatch.StartNew;
    for var I := 0 to 100_000_000 do
      ODict.IndexOf('five');
    T.Stop;
    Writeln('IndexOf unsorted: ', T.Elapsed.ToString);
    writeln;

    writeln ('SortByKeys');
    ODict.SortByKeys;
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    T := TStopwatch.StartNew;
    for var I := 0 to 100_000_000 do
      ODict.IndexOf('five');
    T.Stop;
    Writeln('IndexOf sorted: ', T.Elapsed.ToString);
    writeln;

    writeln ('SortByValues');
    ODict.SortByValues;
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    writeln;

    writeln ('SortByValues plus extra item');
    ODict.Add ('eight', 'Prague');
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    writeln;

    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

这是完整的输出结果:

Natural
one - London
two - Berlin
three - Rome
four - Athens
five - Madrid
six - Bruxelles
seven - Paris
IndexOf unsorted: 00:00:01.2720716

SortByKeys
five - Madrid
four - Athens
one - London
seven - Paris
six - Bruxelles
three - Rome
two - Berlin
IndexOf sorted: 00:00:00.6366114

SortByValues
four - Athens
two - Berlin
six - Bruxelles
one - London
five - Madrid
seven - Paris
three - Rome

SortByValues plus extra item
four - Athens
two - Berlin
six - Bruxelles
one - London
five - Madrid
seven - Paris
three - Rome
eight - Prague

更多 RTL 增强功能

  1. 通过改进 rdMultiString 支持和新方法 ReadNone 和 WriteNone(映射到 REG_NONE Windows 注册表数据类型),扩展了 TRegistry 类。
  2. 改进了 System.DateUtils.RFC822 中的日期支持。
  3. 现在为随 RAD Studio 发布的 Delphi 运行时包提供映射文件

本篇博文就写到这里,希望您能在自己的项目中开始利用这些功能以及最近发布的版本中新增的许多其他 RTL 功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海纳老吴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值