Guest User

Untitled

a guest
Mar 16th, 2021
69
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. program Project1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   System.SysUtils, System.Generics.Collections, System.Math, System.Diagnostics, System.Generics.Defaults,
  9.   SynCommons;
  10.  
  11. type
  12.   TDataLine = class
  13.     SeqNo: integer;
  14.     TransactionID: integer;
  15.     CustomName: string;
  16.   end;
  17.   TDataLineArray = array of TDataLine;
  18.  
  19.   TDataLookup = class
  20.   var
  21.     fData: TObjectList<TDataLine>;
  22.  
  23.     fDataByID: TDictionary<integer, TDataLine>;
  24.     fDataByName: TDictionary<string, TDataLine>;
  25.  
  26.     fSortedById: TArray<TDataLine>;
  27.     fSortedByName: TArray<TDataLine>;
  28.  
  29.     fSynIDs: TSynDictionary;
  30.     fSynNames: TSynDictionary;
  31.  
  32.   public
  33.     constructor Create;
  34.  
  35.     procedure SortByID;
  36.     procedure SortByName;
  37.  
  38.     procedure Add(aTransID: integer; const aName: string);
  39.     function Count: integer;
  40.     function GetAllIDs: TArray<integer>;
  41.     function GetAllNames: TArray<string>;
  42.  
  43.     // Sequenced
  44.     function GetDataName(aID: integer): string;
  45.     function GetDataID(const aName: string): integer;
  46.     function Exists(aID: integer; const aName: string): boolean;
  47.  
  48.     // Dictionary
  49.     function GetNameFromDictionary(aID: integer): string;
  50.     function GetIDFromDictionary(const aName: string): integer;
  51.  
  52.     // TSynDictionary
  53.     function GetNameFromSyn(aID: integer): string;
  54.     function GetIDFromSyn(const aName: string): integer;
  55.  
  56.     // Sorted - TArray.BinarySearch
  57.     function GetNameFromSorted(aID: integer): string;
  58.     function GetIDFromSorted(const aName: string): integer;
  59.  
  60.   end;
  61.  
  62. var
  63.     gDataLookup: TDataLookup;
  64.  
  65. constructor TDataLookup.Create;
  66. begin
  67.   fData       := TObjectList<TDataLine>.Create;
  68.   fDataByID   := TDictionary<integer, TDataLine>.Create;
  69.   fDataByName := TDictionary<string, TDataLine>.Create;
  70.  
  71.   fSynIDs := TSynDictionary.Create(TypeInfo(TIntegerDynArray), TypeInfo(TDataLineArray));
  72.   fSynNames := TSynDictionary.Create(TypeInfo(TStringDynArray), TypeInfo(TDataLineArray));
  73. end;
  74.  
  75.  
  76. function TDataLookup.Count: integer;
  77. begin
  78.   Result := fData.Count;
  79. end;
  80.  
  81. procedure TDataLookup.SortByID;
  82. var
  83.   i: Integer;
  84. begin
  85.   SetLength(fSortedById, fData.Count);
  86.   for i := 0 to Pred(fData.Count) do
  87.   begin
  88.     fSortedById[i]               := TDataLine.Create;
  89.     fSortedById[i].TransactionID := fData.List[i].TransactionID;
  90.     fSortedById[i].CustomName    := fData.List[i].CustomName;
  91.   end;
  92.  
  93.   TArray.Sort<TDataLine>(fSortedById,
  94.   TDelegatedComparer<TDataLine>.Construct(
  95.     function(const Left, Right: TDataLine): Integer
  96.     begin
  97.       if Left.TransactionID > Right.TransactionID then Exit(1);
  98.       if Left.TransactionID < Right.TransactionID then Exit(-1);
  99.       Result:= 0;
  100.     end));
  101. end;
  102.  
  103. procedure TDataLookup.SortByName;
  104. var
  105.   i: Integer;
  106. begin
  107.   SetLength(fSortedByName, fData.Count);
  108.   for i := 0 to Pred(fData.Count) do
  109.   begin
  110.     fSortedByName[i]               := TDataLine.Create;
  111.     fSortedByName[i].TransactionID := fData.List[i].TransactionID;
  112.     fSortedByName[i].CustomName    := fData.List[i].CustomName;
  113.   end;
  114.  
  115.   TArray.Sort<TDataLine>(fSortedByName,
  116.   TDelegatedComparer<TDataLine>.Construct(
  117.     function(const Left, Right: TDataLine): Integer
  118.     begin
  119.       Result := CompareStr(Left.CustomName, Right.CustomName);
  120.     end));
  121. end;
  122.  
  123. procedure TDataLookup.Add(aTransID: integer; const aName: string);
  124. var vData: TDataLine;
  125. begin
  126.   vData := TDataLine.Create;
  127.   vData.TransactionID := aTransID;
  128.   vData.CustomName    := aName;
  129.   vData.SeqNo         := fData.Count + 1;
  130.  
  131.   fData.Add(vData);
  132.   fDataByID.Add(vData.TransactionID, vData);
  133.   fDataByName.Add(vData.CustomName, vData);
  134.  
  135.   fSynIDs.Add(vData.TransactionID, vData);
  136.   fSynNames.Add(vData.CustomName, vData);
  137.  
  138. end;
  139.  
  140. function TDataLookup.GetDataName(aID: integer): string;
  141. var
  142.   i: integer;
  143. begin
  144.   Result := '';
  145.   for i := 0 to Pred(fData.Count) do
  146.     if fData[i].TransactionID = aId then
  147.       Exit(fData[i].CustomName);
  148. end;
  149.  
  150. function TDataLookup.GetNameFromDictionary(aID: integer): string;
  151. var vDataLine: TDataLine;
  152. begin
  153.   if fDataByID.TryGetValue(aID, vDataLine) then
  154.     Result := vDataLine.CustomName;
  155. end;
  156.  
  157. function TDataLookup.GetIDFromDictionary(const aName: string): integer;
  158. var vDataLine: TDataLine;
  159. begin
  160.   Result := 0;
  161.   if fDataByName.TryGetValue(aName, vDataLine) then
  162.     Result := vDataLine.TransactionID;
  163. end;
  164.  
  165. function TDataLookup.GetNameFromSyn(aID: integer): string;
  166. var vDataLine: TDataLine;
  167. begin
  168.   vDataLine := TDataLine(fSynIDs.FindValue(aID)^);
  169.   Result := vDataLine.CustomName;
  170. end;
  171.  
  172. function TDataLookup.GetIDFromSyn(const aName: string): integer;
  173. var vDataLine: TDataLine;
  174. begin
  175.   vDataLine := TDataLine(fSynNames.FindValue(aName)^);
  176.    Result := vDataLine.TransactionID;
  177. end;
  178.  
  179.  
  180. function BinarySearchByID(const aData: TArray<TDataLine>; const aID: integer): integer;
  181. var L, H, i, c: Integer;
  182. begin
  183.   Result := 0;
  184.   L := 0; H := High(aData);
  185.   while L <= H do
  186.   begin
  187.     i := L + (H - L) shr 1;
  188.     c := CompareValue(aData[i].TransactionID, aID);
  189.     if c < 0 then
  190.       L := i + 1
  191.     else
  192.     begin
  193.       if c = 0 then
  194.         Exit(i);
  195.       H := i - 1;
  196.     end;
  197.   end;
  198. end;
  199.  
  200. function BinarySearchByName(const aData: TArray<TDataLine>; const aName: string): integer;
  201. var L, H, i, c: Integer;
  202. begin
  203.   Result := 0;
  204.   L := 0; H := High(aData);
  205.   while L <= H do
  206.   begin
  207.     i := L + (H - L) shr 1;
  208.     c := CompareStr(aData[i].CustomName, aName);
  209.     if c < 0 then
  210.       L := i + 1
  211.     else
  212.     begin
  213.       if c = 0 then
  214.         Exit(aData[i].TransactionID);
  215.       H := i - 1;
  216.     end;
  217.   end;
  218. end;
  219.  
  220. function TDataLookup.GetNameFromSorted(aID: integer): string;
  221. var vDataLine: TDataLine;
  222.     vIdx: integer;
  223. begin
  224.   vDataLine := TDataLine.Create;
  225.   vDataLine.TransactionID := aID;
  226.  
  227.   if TArray.BinarySearch<TDataLine>(fSortedById, vDataLine, vIdx,
  228.     TComparer<TDataLine>.Construct(
  229.       function (const Left, Right: TDataLine): Integer
  230.       begin
  231.        if Left.TransactionID < Right.TransactionID then
  232.           Result := -1
  233.         else if Left.TransactionID > Right.TransactionID then
  234.           Result := 1
  235.         else
  236.           Result := 0;
  237.  
  238.       end
  239.       ))
  240.   then
  241.     Result := fSortedById[vIdx].CustomName;
  242. end;
  243.  
  244. function TDataLookup.GetIDFromSorted(const aName: string): integer;
  245. var vDataLine: TDataLine;
  246.     vIdx: integer;
  247. begin
  248.   Result := 0;
  249.   vDataLine := TDataLine.Create;
  250.   vDataLine.CustomName := aName;
  251.  
  252.  if TArray.BinarySearch<TDataLine>(fSortedByName, vDataLine, vIdx,
  253.     TComparer<TDataLine>.Construct(
  254.       function (const Left, Right: TDataLine): Integer
  255.       begin
  256.         Result := CompareStr(Left.CustomName, Right.CustomName)
  257.       end
  258.       ))
  259.   then
  260.       Result := fSortedByName[vIdx].TransactionID;
  261. end;
  262.  
  263. function TDataLookup.GetDataID(const aName: string): integer;
  264. var
  265.   i: integer;
  266. begin
  267.   Result := 0;
  268.   for i := 0 to Pred(fData.Count) do
  269.     if fData[i].CustomName = aName then
  270.       Exit(fData[i].TransactionID);
  271. end;
  272.  
  273. function TDataLookup.Exists(aID: integer; const aName: string): boolean;
  274. var
  275.   i: Integer;
  276. begin
  277.   Result := false;
  278.   for i := 0 to Pred(fData.Count) do
  279.     if (fData[i].TransactionID = aId) or (fData[i].CustomName = aName) then
  280.       Exit(True);
  281. end;
  282.  
  283. function TDataLookup.GetAllIDs: TArray<integer>;
  284. var
  285.   i: Integer;
  286. begin
  287.   SetLength(Result, fData.Count);
  288.   for i := 0 to Pred(fData.Count) do
  289.     Result[i] := fData.List[i].TransactionID;
  290. end;
  291.  
  292. function TDataLookup.GetAllNames: TArray<string>;
  293. var
  294.   i: Integer;
  295. begin
  296.   SetLength(Result, fData.Count);
  297.   for i := 0 to Pred(fData.Count) do
  298.     Result[i] := fData.List[i].CustomName;
  299. end;
  300.  
  301. const
  302.   cChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  303. function GetRandomString(aNoOfChars: integer): string;
  304. var i: Integer;
  305. begin
  306.   SetLength(Result, aNoOfChars);
  307.   for i := 1 to aNoOfChars do
  308.     Result[i] := cChars[Random(Length(cChars)) + 1];
  309. end;
  310.  
  311. procedure GetRandomDataLine(out aTransID: integer; out aCustomName: string);
  312. begin
  313.   aTransId    := Random(maxint);
  314.   aCustomName := GetRandomString(RandomRange(12, 30));
  315. end;
  316.  
  317. procedure CreateRandomData(var aDataLookup: TDataLookup; aCount: integer);
  318. var
  319.   c: Integer;
  320.   vTransID: integer;
  321.   vCustomName: string;
  322. begin
  323.  aDataLookup := TDataLookup.Create;
  324.  c := 0;
  325.  while c < aCount do
  326.  begin
  327.    GetRandomDataLine(vTransID, vCustomName);
  328.    if Not aDataLookup.Exists(vTransID, vCustomName) then
  329.    begin
  330.      aDataLookup.Add(vTransID, vCustomName);
  331.      inc(c);
  332.    end;
  333.  end;
  334. end;
  335.  
  336. const
  337.   cMaxLoop: integer = 1000000;
  338.   cRunRecords: array of integer = [10, 50, 100, 1000, 10000];
  339.  
  340. var vArrayOfIDs: TArray<integer>;
  341.     vArrayOfNames: TArray<string>;
  342.  
  343. var a, i, vNoOfRecs, vTiming_u, vTiming_d, vTiming_s, vTiming_bs, vTiming_syn: integer;
  344.   vName: string;
  345.   vID: integer;
  346.   vSW: TStopWatch;
  347. begin
  348.   Randomize;
  349.  
  350.   Writeln('Get Name from ID (Search by integer):');
  351.   Writeln('records Sequenced  TArray.BinS  TDict  CustomBinS  TSynDict');
  352.   for vNoOfRecs in cRunRecords do
  353.   begin
  354.     CreateRandomData(gDataLookup, vNoOfRecs);
  355.     try
  356.       vArrayOfIDs := gDataLookup.GetAllIDs;
  357.  
  358.       // Sequenced
  359.       vSW := TStopWatch.StartNew;
  360.       for a := 1 to cMaxLoop div vNoOfRecs do
  361.         for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
  362.           vName := gDataLookup.GetDataName(vArrayOfIDs[i]);
  363.       vTiming_u := vSW.ElapsedMilliseconds;
  364.  
  365.       // Sorted - TArray.BinarySearch
  366.       gDataLookup.SortByID;
  367.       vSW := TStopWatch.StartNew;
  368.       for a := 1 to cMaxLoop div vNoOfRecs  do
  369.         for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
  370.           vName := gDataLookup.GetNameFromSorted(vArrayOfIDs[i]);
  371.       vTiming_s := vSW.ElapsedMilliseconds;
  372.  
  373.       // Dictionary
  374.       vSW := TStopWatch.StartNew;
  375.       for a := 1 to cMaxLoop div vNoOfRecs  do
  376.         for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
  377.           vName := gDataLookup.GetNameFromDictionary(vArrayOfIDs[i]);
  378.       vTiming_d := vSW.ElapsedMilliseconds;
  379.  
  380.       //BinarySearch
  381.       gDataLookup.SortByID;
  382.       vSW := TStopWatch.StartNew;
  383.       for a := 1 to cMaxLoop div vNoOfRecs  do
  384.         for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
  385.           vName := gDataLookup.fSortedById[BinarySearchByID(gDataLookup.fSortedById, vArrayOfIDs[i])].CustomName;
  386.       vTiming_bs := vSW.ElapsedMilliseconds;
  387.  
  388.        // Syn
  389.       vSW := TStopWatch.StartNew;
  390.       for a := 1 to cMaxLoop div vNoOfRecs  do
  391.         for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
  392.           vName := gDataLookup.GetNameFromSyn(vArrayOfIDs[i]);
  393.       vTiming_syn := vSW.ElapsedMilliseconds;
  394.  
  395.       Writeln(Format('%5s    %5s        %4s     %4s       %4s       %4s',[vNoOfRecs.ToString, vTiming_u.ToString, vTiming_s.ToString, vTiming_d.ToString, vTiming_bs.ToString, vTiming_syn.ToString]));
  396.  
  397.     finally
  398.       FreeAndNil(gDataLookup);
  399.     end;
  400.   end;
  401.  
  402.   Writeln;
  403.  
  404.   Writeln('Get ID from Name (Search by string):');
  405.   Writeln('records Sequenced  TArray.BinS  TDict  CustomBinS  TSynDict');
  406.   for vNoOfRecs in cRunRecords do
  407.   begin
  408.     CreateRandomData(gDataLookup, vNoOfRecs);
  409.     try
  410.       vArrayOfNames := gDataLookup.GetAllNames;
  411.  
  412.       // Sequenced
  413.       vSW := TStopWatch.StartNew;
  414.       for a := 1 to cMaxLoop div vNoOfRecs do
  415.         for i := Low(vArrayOfNames) to High(vArrayOfNames) do
  416.           vID := gDataLookup.GetDataID(vArrayOfNames[i]);
  417.       vTiming_u := vSW.ElapsedMilliseconds;
  418.  
  419.       // Sorted - TArray.BinarySearch
  420.       gDataLookup.SortByName;
  421.       vSW := TStopWatch.StartNew;
  422.       for a := 1 to cMaxLoop div vNoOfRecs  do
  423.         for i := Low(vArrayOfNames) to High(vArrayOfNames) do
  424.           vID := gDataLookup.GetIDFromSorted(vArrayOfNames[i]);
  425.       vTiming_s := vSW.ElapsedMilliseconds;
  426.  
  427.       // Dictionary
  428.       vSW := TStopWatch.StartNew;
  429.       for a := 1 to cMaxLoop div vNoOfRecs  do
  430.         for i := Low(vArrayOfNames) to High(vArrayOfNames) do
  431.           vID := gDataLookup.GetIDFromDictionary(vArrayOfNames[i]);
  432.       vTiming_d := vSW.ElapsedMilliseconds;
  433.  
  434.       //BinarySearch
  435.       gDataLookup.SortByName;
  436.       vSW := TStopWatch.StartNew;
  437.       for a := 1 to cMaxLoop div vNoOfRecs  do
  438.         for i := Low(vArrayOfNames) to High(vArrayOfNames) do
  439.           vID := BinarySearchByName(gDataLookup.fSortedByName, vArrayOfNames[i]);
  440.       vTiming_bs := vSW.ElapsedMilliseconds;
  441.  
  442.       //Syn
  443.       vSW := TStopWatch.StartNew;
  444.       for a := 1 to cMaxLoop div vNoOfRecs  do
  445.         for i := Low(vArrayOfNames) to High(vArrayOfNames) do
  446.           vID := gDataLookup.GetIDFromSyn(vArrayOfNames[i]);
  447.       vTiming_syn := vSW.ElapsedMilliseconds;
  448.  
  449.       Writeln(Format('%5s    %5s        %4s     %4s       %4s       %4s',[vNoOfRecs.ToString, vTiming_u.ToString, vTiming_s.ToString, vTiming_d.ToString, vTiming_bs.ToString, vTiming_syn.ToString]));
  450.  
  451.     finally
  452.       FreeAndNil(gDataLookup);
  453.     end;
  454.   end;
  455.  
  456.   Writeln;
  457.   Writeln('done...');
  458.  
  459.   readln;
  460.  
  461. end.
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×