comp.lang.ada
 help / color / mirror / Atom feed
* Variant record memory storage question
@ 2018-08-01 17:38 NiGHTS
  2018-08-01 18:35 ` Shark8
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: NiGHTS @ 2018-08-01 17:38 UTC (permalink / raw)


Say I had a variant record like this:

type Which_One is (Is_Small, Is_Big);

type Variant_Record (Option : Which_One) is 
record
    case Option is
        when Is_Small =>
            Var_1 : Byte -- 1 byte
        when Is_Big =>
            Var_2 : Some_Large_Record -- 1000 bytes
    end case;
end record;

Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or does it act almost like a C union allocating the memory for Variant_Record( Is_Big ) even though it will never morph at run-time?

I am trying to determine the most memory-efficient way to store a complex record and it seems Variant_Record can help me do this, but I am unsure if it will work the way I think it will.

Note I am using gcc. Thank you.

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

* Re: Variant record memory storage question
  2018-08-01 17:38 Variant record memory storage question NiGHTS
@ 2018-08-01 18:35 ` Shark8
  2018-08-01 18:51   ` NiGHTS
  2018-08-01 18:58 ` G.B.
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Shark8 @ 2018-08-01 18:35 UTC (permalink / raw)


On Wednesday, August 1, 2018 at 11:38:06 AM UTC-6, NiGHTS wrote:
> Say I had a variant record like this:
> 
> type Which_One is (Is_Small, Is_Big);
> 
> type Variant_Record (Option : Which_One) is 
> record
>     case Option is
>         when Is_Small =>
>             Var_1 : Byte -- 1 byte
>         when Is_Big =>
>             Var_2 : Some_Large_Record -- 1000 bytes
>     end case;
> end record;
> 
> Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or does it act almost like a C union allocating the memory for Variant_Record( Is_Big ) even though it will never morph at run-time?
> 
> I am trying to determine the most memory-efficient way to store a complex record and it seems Variant_Record can help me do this, but I am unsure if it will work the way I think it will.
> 
> Note I am using gcc. Thank you.

The standard allows for it to be stored as 1-byte, as you desire, but does not require this behavior. Since you are using GCC, I can tell you that it uses the second behavior: because GCC / GNAT views compatibility with C as a very high priority, and also because it's easier to do it that way.

Dmitry, Randy, and/or Simon can probably give you more. (And might have a solution for you.)


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

* Re: Variant record memory storage question
  2018-08-01 18:35 ` Shark8
@ 2018-08-01 18:51   ` NiGHTS
  2018-08-01 19:00     ` G.B.
  0 siblings, 1 reply; 7+ messages in thread
From: NiGHTS @ 2018-08-01 18:51 UTC (permalink / raw)


On Wednesday, August 1, 2018 at 2:35:38 PM UTC-4, Shark8 wrote:
> On Wednesday, August 1, 2018 at 11:38:06 AM UTC-6, NiGHTS wrote:
> > Say I had a variant record like this:
> > 
> > type Which_One is (Is_Small, Is_Big);
> > 
> > type Variant_Record (Option : Which_One) is 
> > record
> >     case Option is
> >         when Is_Small =>
> >             Var_1 : Byte -- 1 byte
> >         when Is_Big =>
> >             Var_2 : Some_Large_Record -- 1000 bytes
> >     end case;
> > end record;
> > 
> > Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or does it act almost like a C union allocating the memory for Variant_Record( Is_Big ) even though it will never morph at run-time?
> > 
> > I am trying to determine the most memory-efficient way to store a complex record and it seems Variant_Record can help me do this, but I am unsure if it will work the way I think it will.
> > 
> > Note I am using gcc. Thank you.
> 
> The standard allows for it to be stored as 1-byte, as you desire, but does not require this behavior. Since you are using GCC, I can tell you that it uses the second behavior: because GCC / GNAT views compatibility with C as a very high priority, and also because it's easier to do it that way.
> 
> Dmitry, Randy, and/or Simon can probably give you more. (And might have a solution for you.)

Could I use a pragma to give the compiler an explicit request to store the data in the smallest possible way? I would think the option should exist to hint to the compiler that I don't care about C compatibility for this record.


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

* Re: Variant record memory storage question
  2018-08-01 17:38 Variant record memory storage question NiGHTS
  2018-08-01 18:35 ` Shark8
@ 2018-08-01 18:58 ` G.B.
  2018-08-01 19:54 ` Niklas Holsti
  2018-08-01 22:30 ` Jeffrey R. Carter
  3 siblings, 0 replies; 7+ messages in thread
From: G.B. @ 2018-08-01 18:58 UTC (permalink / raw)


On 01.08.18 19:38, NiGHTS wrote:
> Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or does it act almost like a C union allocating the memory for Variant_Record( Is_Big ) even though it will never morph at run-time?

(You could also try pragma Unchecked_Union.)

GCC's -gnatRn has hints that will help answer the question.
Using defaults for representation,

package Rep is

     type Byte is mod 512;

     type Some_Large_Array is array (1 .. 1_000) of Byte;

     type Some_Large_Record is
        record
            Data : Some_Large_Array;
        end record;


     type Which_One is (Is_Small, Is_Big);

     type Variant_Record (Option : Which_One) is
        record
            case Option is
               when Is_Small =>
                   Var_1 : Byte; -- 1 byte
               when Is_Big =>
                   Var_2 : Some_Large_Record; -- 1000 bytes
            end case;
        end record;

     S : Variant_Record (Is_Small);

     B : Variant_Record (Is_Big);

end Rep;


$ gcc -c -x ada -gnatR2 rep.ads

Representation information for unit Rep (spec)
----------------------------------------------

for Byte'Object_Size use 16;
for Byte'Value_Size use 9;
for Byte'Alignment use 2;

for Some_Large_Array'Size use 16000;
for Some_Large_Array'Alignment use 2;
for Some_Large_Array'Component_Size use 16;

for Some_Large_Record'Size use 16000;
for Some_Large_Record'Alignment use 2;
for Some_Large_Record use record
    Data at 0 range  0 .. 15999;
end record;

for Which_One'Object_Size use 8;
for Which_One'Value_Size use 1;
for Which_One'Alignment use 1;

for Variant_Record'Object_Size use 16016;
for Variant_Record'Value_Size use ??;
for Variant_Record'Alignment use 2;
for Variant_Record use record
    Option at 0 range  0 ..  7;
    Var_1  at 2 range  0 .. 15;
    Var_2  at 2 range  0 .. 15999;
end record;

for S'Size use 32;
for S'Alignment use 4;

for B'Size use 16016;
for B'Alignment use 2;

-- 
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff


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

* Re: Variant record memory storage question
  2018-08-01 18:51   ` NiGHTS
@ 2018-08-01 19:00     ` G.B.
  0 siblings, 0 replies; 7+ messages in thread
From: G.B. @ 2018-08-01 19:00 UTC (permalink / raw)


On 01.08.18 20:51, NiGHTS wrote:
d I use a pragma to give the compiler an explicit request to store the data in the smallest possible way? I would think the option should exist to hint to the compiler that I don't care about C compatibility for this record.
> 

pragmas Pack, Unchecked_Union,
Size aspects,
record representation clauses,
address overlays.


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

* Re: Variant record memory storage question
  2018-08-01 17:38 Variant record memory storage question NiGHTS
  2018-08-01 18:35 ` Shark8
  2018-08-01 18:58 ` G.B.
@ 2018-08-01 19:54 ` Niklas Holsti
  2018-08-01 22:30 ` Jeffrey R. Carter
  3 siblings, 0 replies; 7+ messages in thread
From: Niklas Holsti @ 2018-08-01 19:54 UTC (permalink / raw)


On 18-08-01 20:38 , NiGHTS wrote:
> Say I had a variant record like this:
>
> type Which_One is (Is_Small, Is_Big);
>
> type Variant_Record (Option : Which_One)
> is record
>    case Option is
>    when Is_Small =>
>       Var_1 : Byte -- 1 byte
>    when Is_Big =>
>       Var_2 : Some_Large_Record -- 1000 bytes
>    end case;
> end record;
>
> Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or
> does it act almost like a C union allocating the memory for
> Variant_Record( Is_Big ) even though it will never morph at
> run-time?

As your type declaration does not give an initial/default value for the 
discriminant (Option) you cannot declare an uninitialized variable of 
this type, but must either constrain it by giving a value to Option:

    V : Variant_Record (Option => Is_Small);

or by giving an initial value to the whole variable:

    V : Variant_Record := <some expression>;

In either case, V.Option is then defined and fixed, and a sensible 
compiler will allocate only as much space as is needed for the variant 
in question.

Note that the same holds for arrays of Variant_Record objects or for 
heap-allocated Variant_Record objects: the value of Option is fixed when 
the object or component is created and cannot change later, but the 
compiler can be expected to allocate only as much space is is needed for 
this value of Option.

Perhaps you intended to provide an initial/default value for Option, as in

    type Variant_Record (Option : Which_One := Is_Small)
    ...

In this case, you can declare variables without an explicit value for 
Option or an explicit whole initial value, as in

    V : Variant_Record;

and you can also change the variant in V by an assignment (of an 
aggregate) to all of V, as in:

   V := (Option => Is_Big, Var_2 => ...);

The amount of memory the compiler allocates for such a variable V is 
compiler-dependent. GNAT (gcc) allocates the maximum amount that might 
be needed, that is, for the Is_Big size in this case.

> I am trying to determine the most memory-efficient way to store a
> complex record and it seems Variant_Record can help me do this, but I
> am unsure if it will work the way I think it will.

It's hard to give more advice without knowing more about your problem. 
Do you have one object of this type, or many? Are you allowed to use 
heap allocation? If you need many objects, are there some limits on how 
many of them are of the Is_Small variant, and how many are Is_Big?

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

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

* Re: Variant record memory storage question
  2018-08-01 17:38 Variant record memory storage question NiGHTS
                   ` (2 preceding siblings ...)
  2018-08-01 19:54 ` Niklas Holsti
@ 2018-08-01 22:30 ` Jeffrey R. Carter
  3 siblings, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2018-08-01 22:30 UTC (permalink / raw)


On 08/01/2018 07:38 PM, NiGHTS wrote:
> 
> type Which_One is (Is_Small, Is_Big);
> 
> type Variant_Record (Option : Which_One) is
> record
>      case Option is
>          when Is_Small =>
>              Var_1 : Byte -- 1 byte
>          when Is_Big =>
>              Var_2 : Some_Large_Record -- 1000 bytes
>      end case;
> end record;
> 
> Will the record Variant_Record( Is_Small ) be stored as 1 byte? Or does it act almost like a C union allocating the memory for Variant_Record( Is_Big ) even though it will never morph at run-time?

As written, a variable

V : Variant_Record (Option => Is_Small);

should use a small amount of memory (typically 2 bytes, or 4 if it's aligning on 
4-byte boundaries). This would be a byte for V.Option and another byte for 
V.Var_1 (and a couple of padding bytes if it needs 4 bytes).

Since V.Option is fixed and cannot be changed, one might think it possible to 
optimize the discriminant away. But since one can also do V.Option'Address, I 
don't think that's often done in practice.

-- 
Jeff Carter
"I didn't squawk about the steak, dear. I
merely said I didn't see that old horse
that used to be tethered outside here."
Never Give a Sucker an Even Break
103

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

end of thread, other threads:[~2018-08-01 22:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-01 17:38 Variant record memory storage question NiGHTS
2018-08-01 18:35 ` Shark8
2018-08-01 18:51   ` NiGHTS
2018-08-01 19:00     ` G.B.
2018-08-01 18:58 ` G.B.
2018-08-01 19:54 ` Niklas Holsti
2018-08-01 22:30 ` Jeffrey R. Carter

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