While the most relevant new features were in other product areas, there are a few enhancements in the Delphi Run Time Library (o RTL) that we thing is worth pointing out.
New TParallelArray Class
There is a new TParallelArray class in the System.Threading unit that enables running operations like &For and Sort in parallel on Array items. On multi core systems, this can speed them up considerably. How can you use it? This is a simple test case, command line project, which creates two identical arrays and sorts them with the regular single-thread Sort and the new parallel version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
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. |
If I run it on my main computer, an Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz , I get the following results, a nice 585% improvement! (output trimmed to milliseconds for readability)
1 2 |
TArray.Sort: 00:00:16.414 TParallelArray.Sort: 00:00:02.889 |
New TOrderedDictionary Class
There is also a new TOrderedDictionary class, derived from TDictionary<K,V>, in the System.Generics.Collections unit. An Ordered Dictionary is a dictionary with integrated sorting methods in the dictionary. This makes is simple to have a for in loop navigating the data in a sorted order, and also makes it faster to locate elements. As an example, take a look at the following project which:
- Creates an ordered dictionary and adds some elements to it
- Displays the output and the time it takes to find a key 100 million times
- Sorts by key, displaying the output again and repeating the 100 million find calls (much faster!)
- Sorts by value and displays again
- Adds an extra element, to prove elements are not added with the sort order, you need to resort as needed (this is generally faster, when inserting multiple elements)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
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. |
This is the complete output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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 |
A Few More RTL Enhancements
- The TRegistry class has been extended with improved rdMultiString support and the new methods ReadNone and WriteNone (which map to the REG_NONE Windows registry data type).
- We improved RFC822 dates support in the System.DateUtils.
- We are now shipping map files for Delphi runtime packages distributed with RAD Studio
That’s all for this blog post, hope you’ll be able to start leveraging these and the many other new RTL features added in recent releases in your projects.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition
Hi you should add a link to the documentation of TParallelArray and all class mentionned
Looks great! Is the “Warm up thread pool” necessary?
In a Windows app the sorting of a TParallelArray takes longer then a “normal” sort. At least on my systems.
Would you be able to email me a trivial example which reproduces this problem? For me, it’s quicker. You can reach me at [email protected]
please add Dark and light option in your website!!