comp.lang.ada
 help / color / mirror / Atom feed
From: "Alex R. Mosteo" <devnull@mailinator.com>
Subject: Efficiency of returning big objects
Date: Mon, 25 Sep 2006 14:14:44 +0200
Date: 2006-09-25T14:14:44+02:00	[thread overview]
Message-ID: <4npvh0FbgbuhU1@individual.net> (raw)

Hello, 

I had a concern over the efficiency of returning big (tagged) types, since I
like to store them in indefinite collections (a la Object'Class) instead of
storing pointers to them. It is said that, as tagged types are passed by
reference, they are always efficiently passed around. However, when you
are /returning/ and not calling, I had my doubts, so I have made this
simple testcase (see at bottom).

Here is a typical execution:

$ ./ref
Direct access: 341312
Indirect access: 76992
Pass constant: 336507
Pass value: 72573

It has been compiled with just gnatmake -O3. It reveals that a copy is
created in the stack for returning every time. I was hoping that, as long
as the type were used as a constant, a reference would be returned and
passed around. This would be very interesting in collections, since we
could do, for example:

Some_Map.Element (Key).Method_Or_Member

without efficiency penalties.

Now, in C++ I would force this behavior explicitly returning references (I
guess this is the usual practice, but I'm not sure). In Ada, I have no idea
how to match this efficient behavior.

So, what do you think? Is there some error in my reasoning or testbed? Is
this a particular shortcoming of this compiler (gnat gpl 2006), or I'm
overlooking something that makes this very non-trivial to implement?

Thanks in advance for your comments,

A. Mosteo.

-------8<---------

with Ada.Calendar; use Ada.Calendar;
with Ada.Text_Io;  use Ada.Text_Io;
procedure Ref is

   type Big_Thing is array (1 .. 64_000) of Character;

   type T is tagged record
      Dummy : Big_Thing := (others => 'c');
      X     : Integer   := 0;
   end record;

   procedure Check (Y : T) is
   begin
      if Y.X /= 0 then
         raise Constraint_Error;
      end if;
   end Check;

   Borg : T;

   function Create return T is
   begin
      return Borg;
   end Create;

   Start : Time;
   Iters : Natural;

begin
   --  Direct access, cheap.
   Iters := 0;
   Start := Clock;
   while Clock - Start < 1.0 loop
      if Borg.X /= 0 then 
         raise Constraint_Error;
      end if;
      Iters := Iters + 1;
   end loop;
   Put_line ("Direct access:" & Natural'Image (Iters));  

   --  Indirect access.
   Iters := 0;
   Start := Clock;
   while Clock - Start < 1.0 loop
      if Create.X /= 0 then 
         raise Constraint_Error;
      end if;
      Iters := Iters + 1;
   end loop;
   Put_line ("Indirect access:" & Natural'Image (Iters));  

   --  Pass by reference, cheap.
   Iters := 0;
   Start := Clock;
   while Clock - Start < 1.0 loop
      Check (Borg);
      Iters := Iters + 1;
   end loop;
   Put_line ("Pass constant:" & Natural'Image (Iters));  

   --  Pass - how?
   Iters := 0;
   Start := Clock;
   while Clock - Start < 1.0 loop
      Check (Create);
      Iters := Iters + 1;
   end loop;
   Put_line ("Pass value:" & Natural'Image (Iters));  
end Ref;

-------8<--------------------------------



             reply	other threads:[~2006-09-25 12:14 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-25 12:14 Alex R. Mosteo [this message]
2006-09-25 13:09 ` Efficiency of returning big objects Dmitry A. Kazakov
2006-09-25 13:51   ` Alex R. Mosteo
2006-09-25 15:24 ` Georg Bauhaus
2006-09-25 16:41   ` Alex R. Mosteo
2006-09-25 19:31 ` Jeffrey R. Carter
2006-09-26  7:45   ` Alex R. Mosteo
2006-09-26  0:33 ` Adam Beneschan
2006-09-26  7:43   ` Alex R. Mosteo
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox