https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117474

            Bug ID: 117474
           Summary: Excessive memory usage during parser stage in
                    interface blocks with types having type-bound
                    procedures
           Product: gcc
           Version: 14.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rimvydas.jas at gmail dot com
  Target Milestone: ---

After addition of init() methods it was noticed that certain scientific model
sources started to require lots of memory to compile.

Derived type by itself is relatively small.
type phys_base_state_type
  real, pointer :: p1  (:,:,:) => null ()
  ! <snip>
contains
  procedure :: init => phys_base_state_type_init
end type

However with addition of type-bound procedures (that take really big type
arguments) blows up both produced module size and memory requirements during
parsing of interface blocks that make use of this type.

$ cat phys_base_state_type_mod.mod | wc -c
2951559
$ zcat phys_base_state_type_mod.mod | wc -c
92422176


Simplified stripped case with 60 interface blocks and no executable code (any
bigger module will do):
$ cat test.f90
subroutine foo
  interface; subroutine foo_part01
    use phys_base_state_type_mod, only : phys_base_state_type
  end subroutine; end interface
! <snip>
  interface; subroutine foo_part60
    use phys_base_state_type_mod, only : phys_base_state_type
  end subroutine; end interface
end subroutine foo

$ /usr/bin/time -v gfortran -I. -c test.f90 -ftime-report 2>&1 | grep -E
"(Maximum|wall|global)"
Time variable                                   usr           sys          wall
          GGC
 parser (global)                    : 144.04 ( 99%)  17.05 (100%) 161.21 ( 99%)
   87M (100%)
        Elapsed (wall clock) time (h:mm:ss or m:ss): 2:44.02
        Maximum resident set size (kbytes): 41411832

Parsing only a single interface block requires just:
        Maximum resident set size (kbytes): 824424

Memory requirements grow linearly with every additional interface block present
in the source code.
It is hard to come up with reasonably small reproducer, since types passed to
INIT() methods have huge nesting of other types with their own type-bound
procedures.

It seems that the phys_base_state_type sym tree is created and populated for
every interface block separately without caching, thus increasing memory
requirements during the parsing stage.
Moreover it should be possible to skip populating type-bound procedure tree
nodes inside the interface blocks, other that they exist.

Reply via email to