[Ada] Single-element Append performance improvement
authorSteve Baird <baird@adacore.com>
Wed, 27 Jul 2022 00:17:17 +0000 (17:17 -0700)
committerMarc Poulhiès <poulhies@adacore.com>
Mon, 5 Sep 2022 07:21:06 +0000 (09:21 +0200)
Ada.Containers.Vectors has two Append procedures that take an
Element value; one takes a Count parameter and one does not
(the count is implicitly one for the latter). For the former version,
there was code that took a faster path if certain conditions were met
and otherwise took a slower path; one of the prerequisite conditions
for this was Count = 1. For the latter version, no such special-case
detection was performed; the more general code was always executed.
Move the special-case detection/handling code from the former version into
the latter and change the former version to simply call the latter version
if Count = 1. Also apply same change to Ada.Containers.Indefinite_Vectors.

gcc/ada/

* libgnat/a-coinve.adb, libgnat/a-convec.adb
(Append): If the Append that takes an Element and a Count is
called with Count = 1, then call the Append that does not take a
Count parameter; otherwise call the code that handles the general
case. Move the special case detection/handling code that was
formerly in that version of Append into the version that does not
take a Count parameter, so that now both versions get the
performance benefit.

gcc/ada/libgnat/a-coinve.adb
gcc/ada/libgnat/a-convec.adb

index c84175a..46d6730 100644 (file)
@@ -197,12 +197,29 @@ is
       Count     : Count_Type)
    is
    begin
-      --  In the general case, we pass the buck to Insert, but for efficiency,
-      --  we check for the usual case where Count = 1 and the vector has enough
-      --  room for at least one more element.
+      --  In the general case, we take the slow path; for efficiency,
+      --  we check for the common case where Count = 1 .
 
-      if Count = 1
-        and then Container.Elements /= null
+      if Count = 1 then
+         Append (Container, New_Item);
+      else
+         Append_Slow_Path (Container, New_Item, Count);
+      end if;
+   end Append;
+
+   ------------
+   -- Append --
+   ------------
+
+   procedure Append (Container : in out Vector;
+                     New_Item  :        Element_Type)
+   is
+   begin
+      --  For performance, check for the common special case where the
+      --  container already has room for at least one more element.
+      --  In the general case, pass the buck to Insert.
+
+      if Container.Elements /= null
         and then Container.Last /= Container.Elements.Last
       then
          TC_Check (Container.TC);
@@ -223,23 +240,11 @@ is
             Container.Elements.EA (New_Last) := new Element_Type'(New_Item);
             Container.Last := New_Last;
          end;
-
       else
-         Append_Slow_Path (Container, New_Item, Count);
+         Insert (Container, Last_Index (Container) + 1, New_Item, 1);
       end if;
    end Append;
 
-   ------------
-   -- Append --
-   ------------
-
-   procedure Append (Container : in out Vector;
-                        New_Item   :        Element_Type)
-   is
-   begin
-      Insert (Container, Last_Index (Container) + 1, New_Item, 1);
-   end Append;
-
    ----------------------
    -- Append_Slow_Path --
    ----------------------
index 3a2adae..751d468 100644 (file)
@@ -173,27 +173,11 @@ is
       Count     : Count_Type)
    is
    begin
-      --  In the general case, we pass the buck to Insert, but for efficiency,
-      --  we check for the usual case where Count = 1 and the vector has enough
-      --  room for at least one more element.
-
-      if Count = 1
-        and then Container.Elements /= null
-        and then Container.Last /= Container.Elements.Last
-      then
-         TC_Check (Container.TC);
-
-         --  Increment Container.Last after assigning the New_Item, so we
-         --  leave the Container unmodified in case Finalize/Adjust raises
-         --  an exception.
-
-         declare
-            New_Last : constant Index_Type := Container.Last + 1;
-         begin
-            Container.Elements.EA (New_Last) := New_Item;
-            Container.Last := New_Last;
-         end;
+      --  In the general case, we take the slow path; for efficiency,
+      --  we check for the common case where Count = 1 .
 
+      if Count = 1 then
+         Append (Container, New_Item);
       else
          Append_Slow_Path (Container, New_Item, Count);
       end if;
@@ -222,7 +206,28 @@ is
                      New_Item  :        Element_Type)
    is
    begin
-      Insert (Container, Last_Index (Container) + 1, New_Item, 1);
+      --  For performance, check for the common special case where the
+      --  container already has room for at least one more element.
+      --  In the general case, pass the buck to Insert.
+
+      if Container.Elements /= null
+        and then Container.Last /= Container.Elements.Last
+      then
+         TC_Check (Container.TC);
+
+         --  Increment Container.Last after assigning the New_Item, so we
+         --  leave the Container unmodified in case Finalize/Adjust raises
+         --  an exception.
+
+         declare
+            New_Last : constant Index_Type := Container.Last + 1;
+         begin
+            Container.Elements.EA (New_Last) := New_Item;
+            Container.Last := New_Last;
+         end;
+      else
+         Insert (Container, Last_Index (Container) + 1, New_Item, 1);
+      end if;
    end Append;
 
    ----------------------