Skip to content

Commit ad7efa4

Browse files
committed
Merge branch 'mr/json_perf' into 'master'
Improve JSON_Value structure performance See merge request eng/toolchain/gnatcoll-core!95
2 parents 2aa9c9b + c6e6b36 commit ad7efa4

File tree

5 files changed

+133
-116
lines changed

5 files changed

+133
-116
lines changed

src/gnatcoll-json.adb

Lines changed: 76 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
------------------------------------------------------------------------------
22
-- G N A T C O L L --
33
-- --
4-
-- Copyright (C) 2011-2022, AdaCore --
4+
-- Copyright (C) 2011-2024, AdaCore --
55
-- --
66
-- This library is free software; you can redistribute it and/or modify it --
77
-- under terms of the GNU General Public License as published by the Free --
@@ -38,6 +38,8 @@ package body GNATCOLL.JSON is
3838
new Ada.Unchecked_Deallocation (JSON_Array_Internal, JSON_Array_Access);
3939
procedure Free is
4040
new Ada.Unchecked_Deallocation (JSON_Object_Internal, JSON_Object_Access);
41+
procedure Free is
42+
new Ada.Unchecked_Deallocation (JSON_String_Internal, JSON_String_Access);
4143

4244
procedure Write
4345
(Item : JSON_Value;
@@ -673,7 +675,7 @@ package body GNATCOLL.JSON is
673675
end;
674676

675677
when JSON_String_Type =>
676-
Append (Ret, JSON.Utility.Escape_String (Item.Data.Str_Value));
678+
Append (Ret, JSON.Utility.Escape_String (Item.Data.Str_Value.Str));
677679

678680
when JSON_Array_Type =>
679681
Append (Ret, '[');
@@ -718,14 +720,14 @@ package body GNATCOLL.JSON is
718720
Do_Indent (Indent + 1);
719721
Append
720722
(Ret,
721-
GNATCOLL.JSON.Utility.Escape_String (Element (J).Key));
723+
GNATCOLL.JSON.Utility.Escape_String (Key (J)));
722724

723725
Append (Ret, ':');
724726
if not Compact then
725727
Append (Ret, ' ');
726728
end if;
727729

728-
Write (Element (J).Val, Compact, Indent + 1, Ret);
730+
Write (Element (J), Compact, Indent + 1, Ret);
729731

730732
Next (J);
731733

@@ -823,19 +825,14 @@ package body GNATCOLL.JSON is
823825
(Val : in out JSON_Value;
824826
Less : access function (Left, Right : JSON_Value) return Boolean)
825827
is
826-
function "<" (Left, Right : Object_Item) return Boolean;
827-
828-
function "<" (Left, Right : Object_Item) return Boolean is
829-
begin
830-
return Less (Left.Val, Right.Val);
831-
end "<";
832-
833-
package Sorting is new Object_Items_Pkg.Generic_Sorting ("<");
828+
-- package Sorting is new Object_Items_Pkg.Generic_Sorting ("<");
834829

835830
begin
836831
case Val.Kind is
837832
when JSON_Array_Type => Sort (Val.Data.Arr_Value.Arr, Less);
838-
when JSON_Object_Type => Sorting.Sort (Val.Data.Obj_Value.Vals);
833+
when JSON_Object_Type =>
834+
-- Sorting.Sort (Val.Data.Obj_Value.Vals);
835+
null;
839836
when others => null;
840837
end case;
841838
end Sort;
@@ -893,6 +890,10 @@ package body GNATCOLL.JSON is
893890
overriding procedure Adjust (Obj : in out JSON_Value) is
894891
begin
895892
case Obj.Data.Kind is
893+
when JSON_String_Type =>
894+
if Obj.Data.Str_Value /= null then
895+
Increment (Obj.Data.Str_Value.Cnt);
896+
end if;
896897
when JSON_Array_Type =>
897898
if Obj.Data.Arr_Value /= null then
898899
Increment (Obj.Data.Arr_Value.Cnt);
@@ -913,6 +914,12 @@ package body GNATCOLL.JSON is
913914
overriding procedure Finalize (Obj : in out JSON_Value) is
914915
begin
915916
case Obj.Data.Kind is
917+
when JSON_String_Type =>
918+
if Obj.Data.Str_Value /= null and then
919+
Decrement (Obj.Data.Str_Value.Cnt)
920+
then
921+
Free (Obj.Data.Str_Value);
922+
end if;
916923
when JSON_Array_Type =>
917924
declare
918925
Arr : JSON_Array_Access := Obj.Data.Arr_Value;
@@ -992,23 +999,31 @@ package body GNATCOLL.JSON is
992999
function Create (Val : UTF8_String) return JSON_Value is
9931000
Ret : JSON_Value;
9941001
begin
995-
Ret.Data := (JSON_String_Type, Str_Value => <>);
996-
Ret.Data.Str_Value.Set (Val);
1002+
Ret.Data := (
1003+
Kind => JSON_String_Type,
1004+
Str_Value => new JSON_String_Internal'
1005+
(Cnt => 1, Str => Null_XString));
1006+
Ret.Data.Str_Value.Str.Set (Val);
9971007
return Ret;
9981008
end Create;
9991009

10001010
function Create (Val : UTF8_Unbounded_String) return JSON_Value is
10011011
Ret : JSON_Value;
10021012
begin
1003-
Ret.Data := (Kind => JSON_String_Type, Str_Value => Null_XString);
1004-
Ret.Data.Str_Value.Set (To_String (Val));
1013+
Ret.Data := (
1014+
Kind => JSON_String_Type,
1015+
Str_Value => new JSON_String_Internal'
1016+
(Cnt => 1, Str => Null_XString));
1017+
Ret.Data.Str_Value.Str.Set (To_String (Val));
10051018
return Ret;
10061019
end Create;
10071020

10081021
function Create (Val : UTF8_XString) return JSON_Value is
10091022
Ret : JSON_Value;
10101023
begin
1011-
Ret.Data := (Kind => JSON_String_Type, Str_Value => Val);
1024+
Ret.Data := (
1025+
Kind => JSON_String_Type,
1026+
Str_Value => new JSON_String_Internal'(Cnt => 1, Str => Val));
10121027
return Ret;
10131028
end Create;
10141029

@@ -1040,14 +1055,10 @@ package body GNATCOLL.JSON is
10401055
(Val : JSON_Value;
10411056
Field_Name : UTF8_String)
10421057
is
1043-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1058+
use Object_Items_Pkg;
1059+
Vals : Object_Items_Pkg.Map renames Val.Data.Obj_Value.Vals;
10441060
begin
1045-
for J in Vals.First_Index .. Vals.Last_Index loop
1046-
if Vals.Element (J).Key = Field_Name then
1047-
Val.Data.Obj_Value.Vals.Delete (J);
1048-
return;
1049-
end if;
1050-
end loop;
1061+
Exclude (Vals, To_XString (Field_Name));
10511062
end Unset_Field;
10521063

10531064
---------------
@@ -1059,37 +1070,21 @@ package body GNATCOLL.JSON is
10591070
Field_Name : UTF8_String;
10601071
Field : JSON_Value)
10611072
is
1062-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1073+
use Object_Items_Pkg;
1074+
Vals : Object_Items_Pkg.Map renames Val.Data.Obj_Value.Vals;
10631075
begin
1064-
for J in Vals.First_Index .. Vals.Last_Index loop
1065-
if Field_Name = Vals.Element (J).Key then
1066-
Vals.Replace_Element (J, (Vals.Element (J).Key, Field));
1067-
return;
1068-
end if;
1069-
end loop;
1070-
1071-
Vals.Append
1072-
(Object_Item'(Key => To_XString (Field_Name),
1073-
Val => Field));
1076+
Include (Vals, To_XString (Field_Name), Field);
10741077
end Set_Field;
10751078

10761079
procedure Set_Field
10771080
(Val : JSON_Value;
10781081
Field_Name : UTF8_XString;
10791082
Field : JSON_Value)
10801083
is
1081-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1084+
use Object_Items_Pkg;
1085+
Vals : Object_Items_Pkg.Map renames Val.Data.Obj_Value.Vals;
10821086
begin
1083-
for J in Vals.First_Index .. Vals.Last_Index loop
1084-
if Field_Name = Vals.Element (J).Key then
1085-
Vals.Replace_Element (J, (Field_Name, Field));
1086-
return;
1087-
end if;
1088-
end loop;
1089-
1090-
Vals.Append
1091-
(Object_Item'(Key => Field_Name,
1092-
Val => Field));
1087+
Include (Vals, Field_Name, Field);
10931088
end Set_Field;
10941089

10951090
procedure Set_Field
@@ -1236,32 +1231,33 @@ package body GNATCOLL.JSON is
12361231

12371232
function Get (Val : JSON_Value) return UTF8_String is
12381233
begin
1239-
return To_String (Val.Data.Str_Value);
1234+
return To_String (Val.Data.Str_Value.Str);
12401235
end Get;
12411236

12421237
function Get (Val : JSON_Value) return UTF8_XString is
12431238
begin
1244-
return Val.Data.Str_Value;
1239+
return Val.Data.Str_Value.Str;
12451240
end Get;
12461241

12471242
function Get (Val : JSON_Value) return UTF8_Unbounded_String is
12481243
begin
1249-
return To_Unbounded_String (Val.Data.Str_Value.To_String);
1244+
return To_Unbounded_String (Val.Data.Str_Value.Str.To_String);
12501245
end Get;
12511246

12521247
function Get
12531248
(Val : JSON_Value;
12541249
Field : UTF8_String) return JSON_Value
12551250
is
1256-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1251+
use Object_Items_Pkg;
1252+
Vals : Object_Items_Pkg.Map renames Val.Data.Obj_Value.Vals;
1253+
Result : Object_Items_Pkg.Cursor;
12571254
begin
1258-
for J in Vals.First_Index .. Vals.Last_Index loop
1259-
if Field = Vals.Element (J).Key then
1260-
return Vals.Element (J).Val;
1261-
end if;
1262-
end loop;
1263-
1264-
return JSON_Null;
1255+
Result := Find (Vals, To_XString (Field));
1256+
if Has_Element (Result) then
1257+
return Element (Result);
1258+
else
1259+
return JSON_Null;
1260+
end if;
12651261
end Get;
12661262

12671263
function Get (Val : JSON_Value) return JSON_Array is
@@ -1274,11 +1270,10 @@ package body GNATCOLL.JSON is
12741270
---------------
12751271

12761272
function Has_Field (Val : JSON_Value; Field : UTF8_String) return Boolean is
1277-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1273+
use Object_Items_Pkg;
1274+
Vals : Object_Items_Pkg.Map renames Val.Data.Obj_Value.Vals;
12781275
begin
1279-
return
1280-
(for some J in Vals.First_Index .. Vals.Last_Index =>
1281-
Field = Vals.Element (J).Key);
1276+
return Has_Element (Find (Vals, To_XString (Field)));
12821277
end Has_Field;
12831278

12841279
---------
@@ -1348,7 +1343,7 @@ package body GNATCOLL.JSON is
13481343
return Create (Val.Data.Flt_Value);
13491344

13501345
when JSON_String_Type =>
1351-
return Create (Val.Data.Str_Value);
1346+
return Create (Val.Data.Str_Value.Str);
13521347

13531348
when JSON_Array_Type =>
13541349
declare
@@ -1365,10 +1360,14 @@ package body GNATCOLL.JSON is
13651360

13661361
when JSON_Object_Type =>
13671362
declare
1363+
use Object_Items_Pkg;
13681364
Result : constant JSON_Value := Create_Object;
1365+
From_Cursor : Cursor := Val.Data.Obj_Value.Vals.First;
13691366
begin
1370-
for E of Val.Data.Obj_Value.Vals loop
1371-
Result.Set_Field (To_String (E.Key), Clone (E.Val));
1367+
while Has_Element (From_Cursor) loop
1368+
Result.Set_Field
1369+
(Key (From_Cursor), Clone (Element (From_Cursor)));
1370+
Next (From_Cursor);
13721371
end loop;
13731372
return Result;
13741373
end;
@@ -1380,7 +1379,6 @@ package body GNATCOLL.JSON is
13801379
---------
13811380

13821381
function "=" (Left, Right : JSON_Value) return Boolean is
1383-
Found : Boolean;
13841382
begin
13851383
if Left.Data.Kind /= Right.Data.Kind then
13861384
return False;
@@ -1400,7 +1398,7 @@ package body GNATCOLL.JSON is
14001398
return Left.Data.Flt_Value = Right.Data.Flt_Value;
14011399

14021400
when JSON_String_Type =>
1403-
return Left.Data.Str_Value = Right.Data.Str_Value;
1401+
return Left.Data.Str_Value.all = Right.Data.Str_Value.all;
14041402

14051403
when JSON_Array_Type =>
14061404
-- Same pointer ?
@@ -1430,24 +1428,12 @@ package body GNATCOLL.JSON is
14301428
then
14311429
return False;
14321430
else
1433-
-- We have the same number of elements, and no duplicates
1434-
for L of Left.Data.Obj_Value.Vals loop
1435-
Found := False;
1436-
for R of Right.Data.Obj_Value.Vals loop
1437-
if R.Key = L.Key then
1438-
if not (R.Val = L.Val) then -- recursive
1439-
return False;
1440-
end if;
1441-
Found := True;
1442-
exit;
1443-
end if;
1444-
end loop;
1445-
1446-
if not Found then
1447-
return False;
1448-
end if;
1449-
end loop;
1450-
return True;
1431+
declare
1432+
use Object_Items_Pkg;
1433+
begin
1434+
return Left.Data.Obj_Value.Vals =
1435+
Right.Data.Obj_Value.Vals;
1436+
end;
14511437
end if;
14521438
end case;
14531439
end "=";
@@ -1460,10 +1446,12 @@ package body GNATCOLL.JSON is
14601446
(Val : JSON_Value;
14611447
CB : access procedure (Name : UTF8_String; Value : JSON_Value))
14621448
is
1463-
Vals : Object_Items_Pkg.Vector renames Val.Data.Obj_Value.Vals;
1449+
use Object_Items_Pkg;
1450+
C : Cursor := Val.Data.Obj_Value.Vals.First;
14641451
begin
1465-
for J in Vals.First_Index .. Vals.Last_Index loop
1466-
CB (To_String (Vals.Element (J).Key), Vals.Element (J).Val);
1452+
while Has_Element (C) loop
1453+
CB (To_String (Key (C)), Element (C));
1454+
Next (C);
14671455
end loop;
14681456
end Map_JSON_Object;
14691457

0 commit comments

Comments
 (0)