comp.lang.ada
 help / color / mirror / Atom feed
* Performance of the Streams 'Read and 'Write
@ 2009-10-29 23:29 Gautier write-only
  2009-10-30  0:39 ` Jeffrey R. Carter
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Gautier write-only @ 2009-10-29 23:29 UTC (permalink / raw)


Hello.
I got used to think that I/O was the last spot where our preferred
language was condemned to slowness.
Now consider this. Variant 1 of a buffered I/O:

  type Buffer is array(Natural range <>) of Unsigned_8;

  procedure Read( b: out Buffer ) is
  begin
    Buffer'Read(Stream(f_in), b);
  exception
    when Ada.Streams.Stream_IO.End_Error =>
      null;
      -- Nothing bad, just some garbage in the buffer
      -- after end of compressed code
  end Read;

  procedure Write( b: in Buffer ) is
  begin
    Buffer'Write(Stream(f_out), b);
  end Write;

Bad luck, it is as slow as doing I/O's with single bytes and
Sequential_IO! But if it is slow by receiving/sending a whole buffer,
how to make it faster ? Now someone (in a slightly different context)
came with this (call it variant 2):

  procedure Read( b: out Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
  end Read;

  procedure Write( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write;

Naively, you would say it is even slower: you do even more by copying
a buffer into another one, right ?
Indeed, not at all, it is *lots* faster (on GNAT and ObjectAda)!
To give an idea, the variant 1 applied to a bzip2 decompressor makes
it 4x slower than the C version, and variant 2 makes it only 7%
slower! With only I/O (like copying a file) you would get an even much
larger difference.

Now, it raises some questions:
Is there maybe a reason in the RM why the 'Read and 'Write have to be
that slow ?
Or are these two compilers lazy when compiling these attributes ?
Should I bug Adacore about that, then ?
Do some other compilers do it better ?
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-29 23:29 Performance of the Streams 'Read and 'Write Gautier write-only
@ 2009-10-30  0:39 ` Jeffrey R. Carter
  2009-10-30  8:58   ` Gautier write-only
  2009-10-30  3:36 ` Georg Bauhaus
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Jeffrey R. Carter @ 2009-10-30  0:39 UTC (permalink / raw)


Gautier write-only wrote:
> 
> Naively, you would say it is even slower: you do even more by copying
> a buffer into another one, right ?
> Indeed, not at all, it is *lots* faster (on GNAT and ObjectAda)!
> To give an idea, the variant 1 applied to a bzip2 decompressor makes
> it 4x slower than the C version, and variant 2 makes it only 7%
> slower! With only I/O (like copying a file) you would get an even much
> larger difference.

And if you overlay the Stream_Element_Array onto the Buffer, thus eliminating 
the copying and the stream attribute operations?

-- 
Jeff Carter
"C's solution to this [variable-sized array parameters] has real
problems, and people who are complaining about safety definitely
have a point."
Dennis Ritchie
25



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-29 23:29 Performance of the Streams 'Read and 'Write Gautier write-only
  2009-10-30  0:39 ` Jeffrey R. Carter
@ 2009-10-30  3:36 ` Georg Bauhaus
  2009-10-30  9:13   ` Gautier write-only
  2009-10-30 13:40 ` Gautier write-only
  2009-11-17 12:57 ` Gautier write-only
  3 siblings, 1 reply; 18+ messages in thread
From: Georg Bauhaus @ 2009-10-30  3:36 UTC (permalink / raw)


On 10/30/09 12:29 AM, Gautier write-only wrote:

>    procedure Write( b: in Buffer ) is
>      use Ada.Streams;
>      First     : constant Stream_Element_Offset:= Stream_Element_Offset
> (b'First);
>      Last      : constant Stream_Element_Offset:= Stream_Element_Offset
> (b'Last);
>      SE_Buffer : Stream_Element_Array (First..Last);
>    begin
>      for i in SE_Buffer'Range loop
>        SE_Buffer(i):= Stream_Element(b(Natural(i)));
>      end loop;
>      Write(Stream(f_out).all, SE_Buffer);
>    end Write;
>
> Naively, you would say it is even slower: you do even more by copying
> a buffer into another one, right ?
> Indeed, not at all, it is *lots* faster (on GNAT and ObjectAda)!


I finally thought that the above procedures are faster than 'Read
or 'Write because the latter are defined in terms of stream elements:
When there is a composite object like b : Buffer and you
'Write it, then for each component of b the corresponding 'Write
is called. This then writes stream elements, probably
calling Stream_IO.Write or some such in the end.
So Write from above appears closer to writing bulk loads
of stream elements than a bulk load of 'Writes can be.

Copying buffers does not matter in comparison to the needs
of I/O (on PCs).



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30  0:39 ` Jeffrey R. Carter
@ 2009-10-30  8:58   ` Gautier write-only
  2009-10-30 19:12     ` Jeffrey R. Carter
  0 siblings, 1 reply; 18+ messages in thread
From: Gautier write-only @ 2009-10-30  8:58 UTC (permalink / raw)


On 30 Okt., 01:39, "Jeffrey R. Carter"
<spam.jrcarter....@spam.acm.org> wrote:

> And if you overlay the Stream_Element_Array onto the Buffer, thus eliminating
> the copying and the stream attribute operations?

With an Unchecked_conversion ?... Sure, but you cannot guarantee that
the Buffer will be packed the same way as Stream_Element_Array on a
compiler X that you don't know. On that type of project (open-source
compression, no compiler/system dependency) I want to avoid any "dirty
trick" like that.
Anyway, the copying takes almost no time. Note that I do not copy
_and_ use the stream attribute at the same time:
Variant 1 uses the stream attribute on Buffer.
Variant 2 copies into a Stream_Element_Array ans uses the Write
procedure in Ada.Streams.

Gautier



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30  3:36 ` Georg Bauhaus
@ 2009-10-30  9:13   ` Gautier write-only
  2009-11-02 21:37     ` Randy Brukardt
  0 siblings, 1 reply; 18+ messages in thread
From: Gautier write-only @ 2009-10-30  9:13 UTC (permalink / raw)


On 30 Okt., 04:36, Georg Bauhaus <rm-host.bauh...@maps.futureapps.de>:

> I finally thought that the above procedures are faster than 'Read
> or 'Write because the latter are defined in terms of stream elements:
> When there is a composite object like b : Buffer and you
> 'Write it, then for each component of b the corresponding 'Write
> is called. This then writes stream elements, probably
> calling Stream_IO.Write or some such in the end.
> So Write from above appears closer to writing bulk loads
> of stream elements than a bulk load of 'Writes can be.

Sure, it is the safe way: write records field by field, arrays element
by element (that recursively). The compiler avoids problems with non-
packed data. Nothing against that. The general case is well done,
fine. But the compiler could have a look a the type left to the
attribute and in such a case (an array of Unsigned_8, or a String)
say: "Gee! that type Buffer is coincidentally the same as
Stream_Element_Array, then I take the shortcut to generate the code to
write the whole buffer and, this time, not the code to write it
element by element".

> Copying buffers does not matter in comparison to the needs of I/O (on PCs).

Right. Variant 2 works fine, but it is an heavy workaround in terms of
source code. Especially for mixed type I/O with plenty of String'Write
and others, you would not want to put the kind of Variant 2 code all
over the place. It  would be a lot better that compilers are able to
take selectively the shortcut form for the attributes.

Gautier



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-29 23:29 Performance of the Streams 'Read and 'Write Gautier write-only
  2009-10-30  0:39 ` Jeffrey R. Carter
  2009-10-30  3:36 ` Georg Bauhaus
@ 2009-10-30 13:40 ` Gautier write-only
  2009-11-02 22:19   ` Gautier write-only
  2009-11-17 12:57 ` Gautier write-only
  3 siblings, 1 reply; 18+ messages in thread
From: Gautier write-only @ 2009-10-30 13:40 UTC (permalink / raw)


Here is a test program. I am curious about other results

-- Usage: test_stream_performance <file>
-- Produces two .tmp files that are copies of <file>.
--
-- Example of output with file m.wmv, 2.59 MB, GNAT GPL 2008 / Win32:
--
--  xxx'Write / xxx'Read (Attribute).. 1.925210886 seconds
--  Workaround with SE buffer......... 0.049318559 seconds
--  Factor 39.036235547

--  Buffer size in bits..... 8192
--  SE Buffer size in bits.. 8192

with Ada.Calendar;                      use Ada.Calendar;
with Ada.Text_IO;
with Ada.Streams.Stream_IO;             use Ada.Streams.Stream_IO;
with Ada.Command_Line;                  use Ada.Command_Line;
with Interfaces;                        use Interfaces;

procedure Test_Stream_Performance is

  f_in, f_out: Ada.Streams.Stream_IO.File_Type;

  buffer_size, SE_buffer_size: Natural:= 0;
  -- To check if buffers could be overlapped (packing)

  type Buffer is array(Natural range <>) of Unsigned_8;

  ------------------------------------------------
  -- 1) Stream attributes - xxx'Read, xxx'Write --
  ------------------------------------------------

  -- Usually we would just have: Buffer'Read(Stream(f_in), b);
  -- Here we care about end of file.

  procedure Read_Attribute( b: out Buffer; last_read: out Natural ) is
    idx: constant Positive_Count:= Index(f_in);
    siz: constant Positive_Count:= Size(f_in);
  begin
    if End_Of_File(f_in) then
      last_read:= b'First-1;
    else
      last_read:= Natural'Min(b'First+Natural(siz-idx),b'Last);
      Buffer'Read(Stream(f_in), b(b'First .. last_read));
    end if;
  end Read_Attribute;

  procedure Write_Attribute( b: in Buffer ) is
  begin
    if buffer_size = 0 then
      buffer_size:= b'size;
    end if;
    Buffer'Write(Stream(f_out), b);
  end Write_Attribute;

  --------------------------------------------
  -- 2) The Stream_Element_Array workaround --
  --------------------------------------------

  procedure Read_SE( b: out Buffer; last_read: out Natural ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
    last_read:= Natural(last);
  end Read_SE;

  procedure Write_SE( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    if SE_buffer_size = 0 then
      SE_buffer_size:= SE_Buffer'size;
    end if;
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE;

  name : constant String:= Argument(1);

  generic
    label: String;
    with procedure Read( b: out Buffer; last_read: out Natural  );
    with procedure Write( b: in Buffer  );
  procedure Test;

  procedure Test is
    b: Buffer(1..1024);
    l: Natural;
  begin
    Open(f_in, In_File, name);
    Create(f_out, Out_File, name & "_$$$_" & label & ".tmp");
    while not End_of_File(f_in) loop
      Read(b,l);
      Write(b(1..l));
    end loop;
    Close(f_out);
    Close(f_in);
  end;

  procedure Test_Attribute is new Test("Attribute", Read_Attribute,
Write_Attribute);
  procedure Test_SE is new Test("SE", Read_SE, Write_SE);

  T0, T1, T2: Time;

  use Ada.Text_IO;

begin
  T0:= Clock;
  Test_Attribute;
  T1:= Clock;
  Test_SE;
  T2:= Clock;
  Put_Line("xxx'Write / xxx'Read (Attribute).." & Duration'Image(T1-
T0) & " seconds");
  Put_Line("Workaround with SE buffer........." & Duration'Image(T2-
T1) & " seconds");
  Put_Line("Factor" & Duration'Image((T1-T0)/(T2-T1)));
  New_Line;
  Put_Line("Buffer size in bits....." & Integer'Image(buffer_size));
  Put_Line("SE Buffer size in bits.." & Integer'Image
(SE_buffer_size));
end;



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30  8:58   ` Gautier write-only
@ 2009-10-30 19:12     ` Jeffrey R. Carter
  2009-10-31 23:46       ` Gautier write-only
                         ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Jeffrey R. Carter @ 2009-10-30 19:12 UTC (permalink / raw)


Gautier write-only wrote:
> On 30 Okt., 01:39, "Jeffrey R. Carter"
> <spam.jrcarter....@spam.acm.org> wrote:
> 
>> And if you overlay the Stream_Element_Array onto the Buffer, thus eliminating
>> the copying and the stream attribute operations?
> 
> With an Unchecked_conversion ?

No, that still does a copy.

Type Buffer, as a simple array of bytes, should have Buffer'Component_Size = 
Unsigned_8'Size by default; but you can specify it if you're paranoid. If you're 
really paranoid, you can add a test that Unsigned_8'Size = Stream_Element'Size, 
which you seem to be assuming. Then

procedure Put (B : in Buffer) is -- Terrible naming scheme.
    subtype Buffer_Stream is Stream_Element_Array (1 .. B'Length);

    S : Buffer_Stream;
    for S'Address use B'Address;
    pragma Import (Ada, S);
begin -- Put
    Write (S);
end Put;

-- 
Jeff Carter
"I spun around, and there I was, face to face with a
six-year-old kid. Well, I just threw my guns down and
walked away. Little bastard shot me in the ass."
Blazing Saddles
40



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30 19:12     ` Jeffrey R. Carter
@ 2009-10-31 23:46       ` Gautier write-only
  2009-11-01 21:38       ` Gautier write-only
  2009-11-02 21:32       ` Randy Brukardt
  2 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-10-31 23:46 UTC (permalink / raw)


On 30 oct, 20:12, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org>
wrote:

> >> And if you overlay the Stream_Element_Array onto the Buffer, thus eliminating
> >> the copying and the stream attribute operations?
>     for S'Address use B'Address;

Bingo!

xxx'Write / xxx'Read (Stream attributes)................ 14.717895000
seconds
Workaround with Stream_Element_Array buffer and copy.... 0.435756000
seconds
Workaround with Stream_Element_Array buffer and overlay. 0.211830000
seconds
Factor (Copy)    33.775541816
Factor (Overlay) 69.479747911

This on a Linux 32 bit netbook, with a 32 MB file; GNAT GPL 2009, -
gnatp -O2.
So my "almost no time" assumption about the buffer copy was definitely
to be understood as "compared to the attribute version"...
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30 19:12     ` Jeffrey R. Carter
  2009-10-31 23:46       ` Gautier write-only
@ 2009-11-01 21:38       ` Gautier write-only
  2009-11-02 21:32       ` Randy Brukardt
  2 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-01 21:38 UTC (permalink / raw)


Jeffrey R. Carter:
> If you're
> really paranoid, you can add a test that Unsigned_8'Size = Stream_Element'Size,
> which you seem to be assuming.

Yet a bit more paranoid: checking the size of arrays!

  workaround_possible: Boolean;

  procedure Check_workaround is
    test_a: constant Byte_Buffer(1..10):= (others => 0);
    test_b: constant Ada.Streams.Stream_Element_Array(1..10):= (others
=> 0);
  begin
    workaround_possible:= test_a'Size = test_b'Size;
  end Check_workaround;

It's the code I've put into Zip-Ada - big success!
:-)
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30 19:12     ` Jeffrey R. Carter
  2009-10-31 23:46       ` Gautier write-only
  2009-11-01 21:38       ` Gautier write-only
@ 2009-11-02 21:32       ` Randy Brukardt
  2 siblings, 0 replies; 18+ messages in thread
From: Randy Brukardt @ 2009-11-02 21:32 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.acm.org> wrote in message 
news:hcfdpo$p62$1@news.tornevall.net...
> Gautier write-only wrote:
>> On 30 Okt., 01:39, "Jeffrey R. Carter"
>> <spam.jrcarter....@spam.acm.org> wrote:
>>
>>> And if you overlay the Stream_Element_Array onto the Buffer, thus 
>>> eliminating
>>> the copying and the stream attribute operations?
>>
>> With an Unchecked_conversion ?
>
> No, that still does a copy.

It doesn't have to, there is a permission to avoid copying in 13.9(12). So 
it depends on what the compiler is able to do optimization-wise.

                                           Randy.





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30  9:13   ` Gautier write-only
@ 2009-11-02 21:37     ` Randy Brukardt
  2009-11-02 22:16       ` Gautier write-only
  0 siblings, 1 reply; 18+ messages in thread
From: Randy Brukardt @ 2009-11-02 21:37 UTC (permalink / raw)


"Gautier write-only" <gautier_niouzes@hotmail.com> wrote in message 
news:715d78f4-9b01-4598-88c1-6fc202983bae@p35g2000yqh.googlegroups.com...
> On 30 Okt., 04:36, Georg Bauhaus <rm-host.bauh...@maps.futureapps.de>:
>
>> I finally thought that the above procedures are faster than 'Read
>> or 'Write because the latter are defined in terms of stream elements:
>> When there is a composite object like b : Buffer and you
>> 'Write it, then for each component of b the corresponding 'Write
>> is called. This then writes stream elements, probably
>> calling Stream_IO.Write or some such in the end.
>> So Write from above appears closer to writing bulk loads
>> of stream elements than a bulk load of 'Writes can be.
>
> Sure, it is the safe way: write records field by field, arrays element
> by element (that recursively). The compiler avoids problems with non-
> packed data. Nothing against that. The general case is well done,
> fine. But the compiler could have a look a the type left to the
> attribute and in such a case (an array of Unsigned_8, or a String)
> say: "Gee! that type Buffer is coincidentally the same as
> Stream_Element_Array, then I take the shortcut to generate the code to
> write the whole buffer and, this time, not the code to write it
> element by element".

IMHO, Ada compilers should do that. (There's specifically a permission to do 
this optimization in Ada 2005: 13.13.2(56/2).) That's an intergral part of 
the stream attribute implementation on Janus/Ada. (Disclaimer: the entire 
stream attribute implementation on Janus/Ada doesn't work right, quite 
probably because it is too complicated. So perhaps there is a reason that 
other Ada compilers don't do that. :-) Note, however, that it is pretty rare 
that you could actually do that (only about 15% of the composite types I've 
seen in Janus/Ada would qualify). So I'm not surprised that implementers 
have left that capability out in favor of things that happen more often.

                             Randy.





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-11-02 21:37     ` Randy Brukardt
@ 2009-11-02 22:16       ` Gautier write-only
  0 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-02 22:16 UTC (permalink / raw)


On 2 nov, 22:37, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> IMHO, Ada compilers should do that. (There's specifically a permission to do
> this optimization in Ada 2005: 13.13.2(56/2).)

Excellent news!

> That's an intergral part of
> the stream attribute implementation on Janus/Ada. (Disclaimer: the entire
> stream attribute implementation on Janus/Ada doesn't work right, quite
> probably because it is too complicated. So perhaps there is a reason that
> other Ada compilers don't do that. :-) Note, however, that it is pretty rare
> that you could actually do that (only about 15% of the composite types I've
> seen in Janus/Ada would qualify).

Sure - but imagine that these 15% might transport 95% of the
information. It could happen, couldn't it ?
And if type T qualifies, a record type R with fields of types T,U,V (U
and V not qualifying) will be also transmitted faster, an array of R
will also go faster, and so on...

> So I'm not surprised that implementers
> have left that capability out in favor of things that happen more often.

I am not surprised either...

Gautier



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30 13:40 ` Gautier write-only
@ 2009-11-02 22:19   ` Gautier write-only
  0 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-02 22:19 UTC (permalink / raw)


Here is the ultimate test ;-), with Jeff's overlay idea and the
unchecked_conversion as well.
G.

-- Usage: test_stream_performance <big_file>
-- Produces .tmp files that are copies of <big_file>.
--
-- Example of output with GNAT GPL 2008 / Win32:
--
--  xxx'Write / xxx'Read (Stream attributes)......... 9.282530042
seconds
--  Workarounds with Stream_Element_Array buffer:
--    copy........................................... 0.444120412
seconds
--    overlay (read), unchecked_conversion (write)... 0.156874407
seconds
--    overlay........................................ 0.150155676
seconds
--  Factor (Copy)    20.900930898
--  Factor (Overlay) 61.819374993

--  Buffer size in bits..... 8192
--  SE Buffer size in bits.. 8192

--  File size in megabytes..... 2.46367E+01

with Ada.Calendar;                      use Ada.Calendar;
with Ada.Text_IO;
with Ada.Streams.Stream_IO;             use Ada.Streams.Stream_IO;
with Ada.Command_Line;                  use Ada.Command_Line;
with Ada.Unchecked_Conversion;
with Interfaces;                        use Interfaces;

procedure Test_Stream_Performance is

  f_in, f_out: Ada.Streams.Stream_IO.File_Type;

  buffer_size, SE_buffer_size: Natural:= 0;
  -- To check if buffers are binary compatible (same packing)

  type Buffer is array(Natural range <>) of Unsigned_8;

  ------------------------------------------------
  -- 1) Stream attributes - xxx'Read, xxx'Write --
  ------------------------------------------------

  -- NB: usually we would just have: Buffer'Read(Stream(f_in), b);
  -- Here we care about end of file.
  --
  procedure Read_Attribute( b: out Buffer; last_read: out Natural ) is
    idx: constant Positive_Count:= Index(f_in);
    siz: constant Positive_Count:= Size(f_in);
  begin
    if End_Of_File(f_in) then
      last_read:= b'First-1;
    else
      last_read:= Natural'Min(b'First+Natural(siz-idx),b'Last);
      Buffer'Read(Stream(f_in), b(b'First .. last_read));
    end if;
  end Read_Attribute;

  procedure Write_Attribute( b: in Buffer ) is
  begin
    if buffer_size = 0 then
      buffer_size:= b'size; -- just for stats
    end if;
    Buffer'Write(Stream(f_out), b);
  end Write_Attribute;

  ---------------------------------------------
  -- 2) The Stream_Element_Array workarounds --
  ---------------------------------------------

  procedure Read_SE_Copy( b: out Buffer; last_read: out Natural ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
    last_read:= Natural(last);
  end Read_SE_Copy;

  procedure Write_SE_Copy( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    if SE_buffer_size = 0 then
      SE_buffer_size:= SE_Buffer'size; -- just for stats
    end if;
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE_Copy;

  -- Overlay idea by Jeff Carter

  procedure Read_SE_Overlay( b: out Buffer; last_read: out Natural )
is
    use Ada.Streams;
    Last: Stream_Element_Offset;
    SE_Buffer : Stream_Element_Array (1..b'Length);
    for SE_Buffer'Address use b'Address;
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    last_read:= b'First + Natural(Last) - 1;
  end Read_SE_Overlay;

  procedure Write_SE_Overlay( b: in Buffer ) is
    use Ada.Streams;
    SE_Buffer : Stream_Element_Array (1..b'Length);
    for SE_Buffer'Address use b'Address;
  begin
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE_Overlay;

  -- Using Unchecked_Conversion

  procedure Write_SE_UC( b: in Buffer ) is
    subtype My_SEA is Ada.Streams.Stream_Element_Array(1..b'Length);
    function To_SEA is new Ada.Unchecked_Conversion(Buffer, My_SEA);
    use Ada.Streams;
  begin
    Write(Stream(f_out).all, To_SEA(b));
  end Write_SE_UC;

  ----------
  -- Test --
  ----------

  function name return String is
  begin
    return Argument(1);
  end;

  generic
    label: String;
    with procedure Read( b: out Buffer; last_read: out Natural  );
    with procedure Write( b: in Buffer  );
  procedure Test;

  procedure Test is
    b: Buffer(1..1024);
    l: Natural;
  begin
    Open(f_in, In_File, name);
    Create(f_out, Out_File, name & "_$$$_" & label & ".tmp");
    while not End_of_File(f_in) loop
      Read(b,l);
      Write(b(1..l));
    end loop;
    Close(f_out);
    Close(f_in);
  end;

  procedure Test_Attribute is new Test("Attribute", Read_Attribute,
Write_Attribute);
  procedure Test_SE_Copy is new Test("SE_Copy", Read_SE_Copy,
Write_SE_Copy);
  procedure Test_SE_Overlay is new Test("SE_Overlay", Read_SE_Overlay,
Write_SE_Overlay);
  procedure Test_SE_UC is new Test("SE_UC", Read_SE_Overlay,
Write_SE_UC);

  T0, T1, T2, T3, T4: Time;

  use Ada.Text_IO;

begin
  if Argument_Count=0 then
    Put_Line(" Usage: test_stream_performance <big_file>");
    Put_Line(" Produces .tmp files that are copies of <big_file>.");
    return;
  end if;
  T0:= Clock;
  Test_Attribute;
  T1:= Clock;
  Test_SE_Copy;
  T2:= Clock;
  Test_SE_Overlay;
  T3:= Clock;
  Test_SE_UC;
  T4:= Clock;
  Put_Line("xxx'Write / xxx'Read (Stream attributes)........." &
Duration'Image(T1-T0) & " seconds");
  Put_Line("Workarounds with Stream_Element_Array buffer:");
  Put_Line("  copy..........................................." &
Duration'Image(T2-T1) & " seconds");
  Put_Line("  overlay (read), unchecked_conversion (write)..." &
Duration'Image(T4-T3) & " seconds");
  Put_Line("  overlay........................................" &
Duration'Image(T3-T2) & " seconds");
  Put_Line("Factor (Copy)   " & Duration'Image((T1-T0)/(T2-T1)));
  Put_Line("Factor (Overlay)" & Duration'Image((T1-T0)/(T3-T2)));
  New_Line;
  Put_Line("Buffer size in bits....." & Integer'Image(buffer_size));
  Put_Line("SE Buffer size in bits.." & Integer'Image
(SE_buffer_size));
  New_Line;
  Open(f_in, In_File, name);
  Put_Line("File size in megabytes....." & Float'Image(Float(Size
(f_in))/(1024.0*1024.0)));
  Close(f_in);
end;




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-10-29 23:29 Performance of the Streams 'Read and 'Write Gautier write-only
                   ` (2 preceding siblings ...)
  2009-10-30 13:40 ` Gautier write-only
@ 2009-11-17 12:57 ` Gautier write-only
  2009-11-17 13:26   ` Ludovic Brenta
                     ` (2 more replies)
  3 siblings, 3 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-17 12:57 UTC (permalink / raw)


Hello,
I have an idea about how to patch GNAT on this.
Indeed, there is already a fast Stream exchangein GNAT, only for the
{Wide_}String types.
So, at the end of Find_Stream_Subprogram, exp_attr.adb, I would add
something like

if Is_Array_Type(Typ) and then
  Is_Bit_Packed_Array (Typ) and then
  Component_Size (Typ) = 8 and then
then
  Comp_Typ:= Component_Type (Typ);
  if Is_Modular_Integer_Type(Comp_Typ) and then
    [modulus ??] (Comp_Typ) = 2**8
  then
    [ go ahead with some unchecked conversion to String ]
    return [the right thing];
  end if;
end if;

Now, I have no experience with building GNAT, from the GCC tree.
Would someone like to help ?
Or is it easy to on Windows (currently, no Linux available on my
side) ?
TIA
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-11-17 12:57 ` Gautier write-only
@ 2009-11-17 13:26   ` Ludovic Brenta
  2009-11-17 20:19   ` Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write) Tero Koskinen
  2009-11-26 13:23   ` Performance of the Streams 'Read and 'Write Gautier write-only
  2 siblings, 0 replies; 18+ messages in thread
From: Ludovic Brenta @ 2009-11-17 13:26 UTC (permalink / raw)


Gautier wrote on comp.lang.ada:
> Now, I have no experience with building GNAT, from the GCC tree.
> Would someone like to help ?
> Or is it easy to on Windows (currently, no Linux available on my
> side) ?
> TIA

http://goodbye-microsoft.com/ :)

*ducks and hides*

--
Ludovic Brenta.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write)
  2009-11-17 12:57 ` Gautier write-only
  2009-11-17 13:26   ` Ludovic Brenta
@ 2009-11-17 20:19   ` Tero Koskinen
  2009-11-18 10:55     ` Gautier write-only
  2009-11-26 13:23   ` Performance of the Streams 'Read and 'Write Gautier write-only
  2 siblings, 1 reply; 18+ messages in thread
From: Tero Koskinen @ 2009-11-17 20:19 UTC (permalink / raw)


On Tue, 17 Nov 2009 04:57:26 -0800 (PST) Gautier write-only wrote:
> Now, I have no experience with building GNAT, from the GCC tree.
> Would someone like to help ?
> Or is it easy to on Windows (currently, no Linux available on my
> side) ?

Building GNAT on Windows should work as long as you have binary version
of GNAT already installed.

Search for cygwin or mingw. Also, look at avr-ada and gnuada projects
at sourceforge.net for examples.

Some links:
http://sourceforge.net/apps/mediawiki/avr-ada/index.php?title=BuildScript

http://gnuada.sourceforge.net/

http://en.wikibooks.org/wiki/Ada_Programming/Installing

http://ada.krischik.com/index.php/Articles/CompileGNATGPL?from=Articles.CompileGNAT

-- 
Tero Koskinen - http://iki.fi/tero.koskinen/



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write)
  2009-11-17 20:19   ` Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write) Tero Koskinen
@ 2009-11-18 10:55     ` Gautier write-only
  0 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-18 10:55 UTC (permalink / raw)


Thanks Tero, the links are very useful and informative.
If it sorts out to be too complicated for me, at least it gives me
ideas on how to find motivated people...
For example AVR-Ada might benefit a lot from a speedup of any
Byte_Array'Read / 'Write :-).
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Performance of the Streams 'Read and 'Write
  2009-11-17 12:57 ` Gautier write-only
  2009-11-17 13:26   ` Ludovic Brenta
  2009-11-17 20:19   ` Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write) Tero Koskinen
@ 2009-11-26 13:23   ` Gautier write-only
  2 siblings, 0 replies; 18+ messages in thread
From: Gautier write-only @ 2009-11-26 13:23 UTC (permalink / raw)


> I have an idea about how to patch GNAT on this.

Someone might be quicker than me in doing that...
Just in case, another good place (or even a better one) for inserting
the shortcut would be:
Build_Array_Read_Write_Procedure in exp_strm.adb .
Multi-dimensional arrays could be considered there as well, if they
comply of course.
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!




^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2009-11-26 13:23 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-29 23:29 Performance of the Streams 'Read and 'Write Gautier write-only
2009-10-30  0:39 ` Jeffrey R. Carter
2009-10-30  8:58   ` Gautier write-only
2009-10-30 19:12     ` Jeffrey R. Carter
2009-10-31 23:46       ` Gautier write-only
2009-11-01 21:38       ` Gautier write-only
2009-11-02 21:32       ` Randy Brukardt
2009-10-30  3:36 ` Georg Bauhaus
2009-10-30  9:13   ` Gautier write-only
2009-11-02 21:37     ` Randy Brukardt
2009-11-02 22:16       ` Gautier write-only
2009-10-30 13:40 ` Gautier write-only
2009-11-02 22:19   ` Gautier write-only
2009-11-17 12:57 ` Gautier write-only
2009-11-17 13:26   ` Ludovic Brenta
2009-11-17 20:19   ` Building GNAT on Windows (Was: Re: Performance of the Streams 'Read and 'Write) Tero Koskinen
2009-11-18 10:55     ` Gautier write-only
2009-11-26 13:23   ` Performance of the Streams 'Read and 'Write Gautier write-only

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