Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very long build times for anything besides a trivial specification #1293

Closed
dalybrown opened this issue Nov 7, 2023 · 21 comments
Closed

Very long build times for anything besides a trivial specification #1293

dalybrown opened this issue Nov 7, 2023 · 21 comments

Comments

@dalybrown
Copy link

Hello,

This is more of a question than an issue. My build times are extremely long for anything besides a trivial RecordFlux specification. Often times, I run out of memory. I've tried removing parallel compilation to (presumably) consume less memory but it takes forever (hour++) for just a trivial (in my opinion) example.

The specification I'm trying to model has a general format for messages, and then I use type refinement based on some fields in the common part. After implementing the specification for one of the refinements, and just a placeholder for a second, the build times seem to increase exponentially. I should mention that there are many conditional fields and so the transition logic between each field has many guard conditions.

Is this expected? Should we be using a (extremely) beefy server to build anything that uses RecordFlux generated code? Are we using the wrong tool here? Maybe this is documented somewhere some of these limitations but I can't find them.

@treiher
Copy link
Collaborator

treiher commented Nov 7, 2023

Hi Daly,

This is not a known problem. Typically, the compilation takes only a couple of seconds on a modern workstation, even for code generated from a complex specification. In the past, we have observed that certain compiler flags can negatively affect the compilation time, but the resulting compilation time was always still in the order of minutes, not hours.

Which toolchain are you using? Do you use specific compiler flags? Could you provide a small reproducer, where this issue can be observed?

@dalybrown
Copy link
Author

Thanks for the quick reply. It seemed off to me too - I expect a few seconds to a few minutes to build. I can put together a reproducer and send to you this week.

Here are the compiler flags I am running with at the moment (I use Alire to manage my projects):

"-Og" -- Optimize for debug
,"-ffunction-sections" -- Separate ELF section for each function
,"-fdata-sections" -- Separate ELF section for each variable
,"-g" -- Generate debug info
,"-gnatwa" -- Enable all warnings
,"-gnatw.X" -- Disable warnings for No_Exception_Propagation
,"-gnatVa" -- All validity checks
,"-gnaty3" -- Specify indentation level of 3
,"-gnatya" -- Check attribute casing
,"-gnatyA" -- Use of array index numbers in array attributes
,"-gnatyB" -- Check Boolean operators
,"-gnatyb" -- Blanks not allowed at statement end
,"-gnatyc" -- Check comments
,"-gnaty-d" -- Disable check no DOS line terminators present
,"-gnatye" -- Check end/exit labels
,"-gnatyf" -- No form feeds or vertical tabs
,"-gnatyh" -- No horizontal tabs
,"-gnatyi" -- Check if-then layout
,"-gnatyI" -- check mode IN keywords
,"-gnatyk" -- Check keyword casing
,"-gnatyl" -- Check layout
,"-gnatym" -- Check maximum line length
,"-gnatyn" -- Check casing of entities in Standard
,"-gnatyO" -- Check that overriding subprograms are explicitly marked as such
,"-gnatyp" -- Check pragma casing
,"-gnatyr" -- Check identifier references casing
,"-gnatyS" -- Check no statements after THEN/ELSE
,"-gnatyt" -- Check token spacing
,"-gnatyu" -- Check unnecessary blank lines
,"-gnatyx" -- Check extra parentheses
,"-gnatX" -- Enable GNAT Extensions

I should mention I'm using a Debian based docker container run on a Mac M1 (so the Debian container is an arm64 architecture, running natively and not using Rosetta). This isn't an issue normally: I have great performance developing in Ada/SPARK with this setup. I should also mention that the issue is also reproduced in our pipeline: we use GitLab internally and even on their beefier amd64 shared runners it was taking 1 hour++ (and burning our CI minutes :( ).

I'm using the following version of gnat:

GNAT 13.2.0
Copyright (C) 1996-2023, Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I'm using the latest version of RecordFlux from pypi: 0.14.0.

I'll make a reproducer that is a bit simpler than what I have but still demonstrates what is happening.

@dalybrown
Copy link
Author

Here is a very basic example: this reproducer will only take a couple of minutes to build for me, but it shows the issue starting to creep in. Maybe I am not using the generated code properly and that is the issue.

To really expose my issue, I can add in more conditionals on the transitions and more fields in the messages to really highlight it (and make it more similar to the real messages we are trying to model). I'll hold off on that if this reproducer is good enough.

Let me know, thanks!

reproducer.tar.gz

@treiher
Copy link
Collaborator

treiher commented Nov 8, 2023

Thank you for the reproducer. A build time of a couple of minutes is much longer than we have seen with much more complicated specifications. We will investigate and let you know when we know more.

@dalybrown
Copy link
Author

Thanks!

And to be clear: I trimmed this down quite a bit from the real application we are building. The message structure is similar but larger and more complicated and building takes 1 hour++.

@treiher
Copy link
Collaborator

treiher commented Nov 9, 2023

The long compilation time is caused by the use of the -gnatX flag. When the flag is removed, your reproducer builds in less than a second. It is unexpected that -gnatX has such a severe impact and I have informed the compiler team about the problem. For now, the only workaround I can see is not to use -gnatX.

@dalybrown
Copy link
Author

Ahhhh thanks! Doh! I should of tried that instead of trying a bunch of other flags.

@dalybrown
Copy link
Author

I should mention the same issue occurs with -gnat2022, so it's not just the -gnatX GNAT extensions.

@dalybrown
Copy link
Author

Also, to avoid creating another issue, I've had problems with some more compiler switches:

  • GNAT style checks fail. I tried to run the generated files through the pretty printer to fix some of them but the GNAT pretty printer crashes. I've raised an issue for that one: gnatpp crashes when setting -c3 to format commments and comment has no characters libadalang-tools#29. For now, I use sed to prepend pragma Style_Checks (Off); to every generated file. I'm using the Alire validation profile to run these checks.

  • -gnatwq causes issues for some of the generated code. For example (from the reproducer): recordflux-build/generated/rflx-variant_two-data.adb:628:52: warning: equality should be parenthesized here [-gnatwq].

  • -gnatw.a causes issues in the generated code. For example (not from the reproducer but from my own specs): warning: in instantiation at rflx-rflx_message_sequence.ads:54 [-gnatw.a] and warning: check will fail at run time [-gnatw.a]. The line it is pointing to is here:

  procedure Initialize (Ctx : out Context; Buffer : in out RFLX_Types.Bytes_Ptr) with
    Pre =>
      (not Ctx'Constrained
       and then Buffer /= null
       and then Buffer'Length > 0
       and then Buffer'Last < RFLX_Types.Index'Last),
    Post =>
      (Has_Buffer (Ctx)
       and Valid (Ctx)
       and Buffer = null
       and Ctx.Buffer_First = Buffer'First'Old
       and Ctx.Buffer_Last = Buffer'Last'Old
       and Ctx.First = RFLX_Types.To_First_Bit_Index (Ctx.Buffer_First)
       and Ctx.Last = RFLX_Types.To_Last_Bit_Index (Ctx.Buffer_Last)
       and Sequence_Last (Ctx) = Ctx.First - 1),
    Depends =>
      (Ctx => Buffer, Buffer => null);

Cheers!

@treiher
Copy link
Collaborator

treiher commented Nov 10, 2023

I already have seen some style check warnings in your reproducer. These warnings were caused by the use of -gnatyc ("Check comments, double space.") which enforces a different spacing than -gnatyC ("Check comments, single space.") that we use for our code. We already use pragma Style_Checks to prevent such issues, but as this pragma is placed after the license header, GNAT still complains about the spacing there. We consider moving the pragma Style_Checks to the top of the file to prevent this issue. Did you see any other style issues?

  • -gnatwq causes issues for some of the generated code. For example (from the reproducer): recordflux-build/generated/rflx-variant_two-data.adb:628:52: warning: equality should be parenthesized here [-gnatwq].

I cannot reproduce the issue with RecordFlux 0.15.0. Please check if upgrading RecordFlux solves the issue for you.

  • -gnatw.a causes issues in the generated code. For example (not from the reproducer but from my own specs): warning: in instantiation at rflx-rflx_message_sequence.ads:54 [-gnatw.a] and warning: check will fail at run time [-gnatw.a]. The line it is pointing to is here:
  procedure Initialize (Ctx : out Context; Buffer : in out RFLX_Types.Bytes_Ptr) with
    Pre =>
      (not Ctx'Constrained
       and then Buffer /= null
       and then Buffer'Length > 0
       and then Buffer'Last < RFLX_Types.Index'Last),
    Post =>
      (Has_Buffer (Ctx)
       and Valid (Ctx)
       and Buffer = null
       and Ctx.Buffer_First = Buffer'First'Old
       and Ctx.Buffer_Last = Buffer'Last'Old
       and Ctx.First = RFLX_Types.To_First_Bit_Index (Ctx.Buffer_First)
       and Ctx.Last = RFLX_Types.To_Last_Bit_Index (Ctx.Buffer_Last)
       and Sequence_Last (Ctx) = Ctx.First - 1),
    Depends =>
      (Ctx => Buffer, Buffer => null);

I have seen this warning when using -gnatVo. The only workaround I know is to not enable this switch. The bug does not exist in recent GNAT Pro releases. Only the FSF GNAT 13 seems to be affected, so it could make sense to report the issue to the FSF.

@dalybrown
Copy link
Author

Awesome - thanks for the response! We are using 0.14.0 version of RecordFlux so I'll update today and check again. Cheers!

@dalybrown
Copy link
Author

After updating to 0.15.0 I can confirm that the -gnatwq has been addressed and the -gnatw.a seems to have also gone away. (The installation issue I had raised in another issue is also fixed!).

Thanks for everything!

@treiher
Copy link
Collaborator

treiher commented Nov 13, 2023

You are welcome! I'm glad to hear that most of your issues have been resolved in the new version. We will probably also fix the style check problem soon.

adacore-bot pushed a commit that referenced this issue Dec 4, 2023
Ref. #1293, eng/recordflux/RecordFlux#1461
@treiher
Copy link
Collaborator

treiher commented Dec 5, 2023

The style check warnings for the license header have been fixed in fbecae0.

@treiher treiher closed this as completed Dec 5, 2023
@dalybrown
Copy link
Author

The long compilation time is caused by the use of the -gnatX flag. When the flag is removed, your reproducer builds in less than a second. It is unexpected that -gnatX has such a severe impact and I have informed the compiler team about the problem. For now, the only workaround I can see is not to use -gnatX.

Has any progress been made here? It's not just -gnatX: it's any Ada2022 flag. I don't have a good workaround at the moment for code written to use Ada2022 to also make use of RecordFlux ... I just can't build it at all. Thanks!

@treiher
Copy link
Collaborator

treiher commented Jan 12, 2024

The fix is currently in progress. Unfortunately, it appears to be a difficult problem and it is not yet clear how long it will take to complete.

As a workaround you could try to set the -gnatX or -gnat2022 flag on a per-file basis in the project file, but this will only help for files that don't use RecordFlux directly.

@dalybrown
Copy link
Author

The fix is currently in progress. Unfortunately, it appears to be a difficult problem and it is not yet clear how long it will take to complete.

As a workaround you could try to set the -gnatX or -gnat2022 flag on a per-file basis in the project file, but this will only help for files that don't use RecordFlux directly.

Thanks for the response! And glad to hear it is in progress :). I'll try your suggestion, I wasn't sure how to mix and match the two to be honest. The combinations I had tried so far weren't working as I expected. I'll try out your suggestion! The alternative which I think will work is to build my RecordFlux project as a separate library and link it.

@dalybrown
Copy link
Author

So adding pragma Ada_2012 to all the generated code solves the problem! I think that would be a good thing to include automatically as part of the rflx generate command so that others don't run into the issue. It is true either way that the code doesn't compile with Ada2022+ so probably a nice informative thing to put for now!

@senier
Copy link
Member

senier commented Jan 13, 2024

So adding pragma Ada_2012 to all the generated code solves the problem! I think that would be a good thing to include automatically as part of the rflx generate command so that others don't run into the issue. It is true either way that the code doesn't compile with Ada2022+ so probably a nice informative thing to put for now!

Great to hear and thanks for reporting back! Adding that pragma to the generated code should be easy to do. I created an internal ticket for that.

@senier
Copy link
Member

senier commented Jan 22, 2024

@dalybrown This is to let you know that pragma Ada_2012 is now automatically added to all generated files. That change is on main and will be part of the next public release.

@dalybrown
Copy link
Author

Awesome - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants