Performance of the Streams 'Read and 'Write

91 views
Skip to first unread message

Gautier write-only

unread,
Oct 29, 2009, 7:29:47 PM10/29/09
to
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!

Jeffrey R. Carter

unread,
Oct 29, 2009, 8:39:39 PM10/29/09
to
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

Georg Bauhaus

unread,
Oct 29, 2009, 11:36:27 PM10/29/09
to
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).

Gautier write-only

unread,
Oct 30, 2009, 4:58:15 AM10/30/09
to
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

Gautier write-only

unread,
Oct 30, 2009, 5:13:19 AM10/30/09
to
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

Gautier write-only

unread,
Oct 30, 2009, 9:40:27 AM10/30/09
to
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;

Jeffrey R. Carter

unread,
Oct 30, 2009, 3:12:18 PM10/30/09
to
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

Gautier write-only

unread,
Oct 31, 2009, 7:46:32 PM10/31/09
to
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 write-only

unread,
Nov 1, 2009, 4:38:44 PM11/1/09
to
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!
:-)

Randy Brukardt

unread,
Nov 2, 2009, 4:32:51 PM11/2/09
to
"Jeffrey R. Carter" <spam.jrc...@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.


Randy Brukardt

unread,
Nov 2, 2009, 4:37:48 PM11/2/09
to
"Gautier write-only" <gautier...@hotmail.com> wrote in message
news:715d78f4-9b01-4598...@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.


Gautier write-only

unread,
Nov 2, 2009, 5:16:30 PM11/2/09
to
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

Gautier write-only

unread,
Nov 2, 2009, 5:19:48 PM11/2/09
to
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;

Message has been deleted

Gautier write-only

unread,
Nov 17, 2009, 7:57:26 AM11/17/09
to
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

Ludovic Brenta

unread,
Nov 17, 2009, 8:26:12 AM11/17/09
to
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.

Tero Koskinen

unread,
Nov 17, 2009, 3:19:34 PM11/17/09
to
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/

Gautier write-only

unread,
Nov 18, 2009, 5:55:34 AM11/18/09
to
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 write-only

unread,
Nov 26, 2009, 8:23:22 AM11/26/09
to
> 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.

Reply all
Reply to author
Forward
0 new messages