From: John Perry <john.perry@usm.edu>
Subject: Re: Performance of records with variant parts
Date: Wed, 31 Mar 2021 17:03:10 -0700 (PDT) [thread overview]
Message-ID: <9233bc10-091c-46af-b613-504bcb5e1c82n@googlegroups.com> (raw)
In-Reply-To: <8f009bf0-d5a3-42b8-9bd9-12bce24f1093n@googlegroups.com>
On Tuesday, March 30, 2021 at 2:12:36 AM UTC-5, briot.e...@gmail.com wrote:
> Since you are on linux, you might want to look at `perf` for performance analysis:
>
> perf record --call-graph=fp your_program
> perf report -g
I don't know why I didn't think of that; I've used perf before. It took a while to find the problem (inlining was an issue), but that did the trick! Both variant and non-variant versions now perform at the same speed.
The problem was indeed a different location. A function returns an Intersection_Type, which has several fields, one of which was a Thing_Type. So if Thing_Type is variant, Intersection_Type also has to be variant. The non-variant version in Ada was
| return (
| if which = 0 then No_Intersection
| else (
| thing => things(which),
| ray => ray,
| dist => dist(which)
| )
| );
...and -gnatD's output for the non-variant version was
| return (if which = 0 then objects__no_intersection else (
| thing => things (which),
| ray => ray,
| dist => dist (which)));
The non-variant Ada version was:
| return (
| if which = 0 then No_Intersection
| else (
| kind => things(which).kind,
| thing => things(which),
| ray => ray,
| dist => dist(which)
| )
| );
The -gnatD option (thanks, Simon!) translates this as:
| R79b : constant objects__object_type := things (which).kind;
| type objects__intersections__A84b is access all
| objects__intersection_type;
| freeze objects__intersections__A84b []
| R83b : constant objects__intersections__A84b := (if which = 0
| then objects__no_intersection else
| do
| [subtype objects__intersections__T78b is
| objects__intersection_type (R79b)]
| A81b : objects__intersections__T78b;
| A81b.kind := R79b;
| A81b.thing := things (which);
| A81b.ray := ray;
| A81b.dist := dist (which);
| in A81b end
| )'reference;
| R87b : constant objects__object_type := (R83b.all).kind;
| subtype objects__intersections__S86b is
| objects__intersection_type (R87b);
| return (objects__intersections__S86b!((R83b.all)));
That's... wow. Anyone know why all that is necessary? It seems to create a new inline type instead of using the existing type.
Studying the code, I realized that there was no reason that Intersections_Type had to keep a copy of thing(which); it could instead just remember which, and the caller could obtain thing(which) directly.
That's it. There was nothing else to change.
thank you again, very much
john perry
next prev parent reply other threads:[~2021-04-01 0:03 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-22 17:02 Performance of records with variant parts John Perry
2021-03-22 17:32 ` Jeffrey R. Carter
2021-03-22 17:49 ` John Perry
2021-03-22 17:54 ` John Perry
2021-03-22 19:31 ` Jeffrey R. Carter
2021-03-22 22:11 ` John Perry
2021-03-23 9:31 ` Jeffrey R. Carter
2021-03-23 14:27 ` Simon Wright
2021-03-23 23:00 ` John Perry
2021-03-23 23:27 ` Jeffrey R. Carter
2021-03-26 15:38 ` Stephen Leake
2021-03-26 15:44 ` John Perry
2021-03-30 7:12 ` Emmanuel Briot
2021-04-01 0:03 ` John Perry [this message]
2021-04-01 6:45 ` Emmanuel Briot
2021-04-01 13:38 ` Niklas Holsti
2021-04-02 16:07 ` John Perry
2021-03-22 17:39 ` Dmitry A. Kazakov
2021-03-22 17:45 ` John Perry
2021-03-22 18:07 ` Dmitry A. Kazakov
2021-03-22 18:23 ` John Perry
2021-03-22 20:30 ` Dmitry A. Kazakov
2021-03-22 18:59 ` Niklas Holsti
2021-03-22 21:54 ` John Perry
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox