Bug 1 — ir-hlc.bas accumulates the emitted C in a STRING, making emission O(n²)
fb_StrConcatAssign() calls fb_hStrRealloc( dst, dst_len+src_len, TRUE ), and fb_hStrRealloc() (src/rtlib/str_core.c:97) over-allocates by only 12.5 %:
12.5 % headroom on a multi-megabyte block, on a heap already holding the whole symbol table and AST, means realloc() cannot extend in place and copies the buffer. The result is Θ(n²) bytes memcpy'd over the emission of an n-byte listing.
Instrumenting sectionWriteLine() on an 11.8 MB listing: 308,130 calls, 10.6 MB of text written, 19.6 s spent inside that one sub out of a 31.5 s run. The mean .text length at append time was 116 KB, so the appends alone moved ≈ 35 GB.
Bug 2 — fbc passes -Wall to gcc without -Wno-misleading-indentation, and that warning is quadratic on gcc < 10
On gcc 9.3 that warning is quadratic in the size of the translation unit — it resolves source lines through the front end's line cache, and on a large file the repeated non-monotonic lookups degrade badly.
Note: These problems exist on fbc compilers even before version 1.20.0
The changes/patches pass all FBC's unit tests.
I have personally experienced my large FB projects dropping from 40+ seconds to 3.5 seconds compile times.
Attachments:
REPORT.md - the actual bug report
0001-ir-hlc-section-buffer.patch - Bug 1 fix, -p1 against master
0002-gcc-wno-misleading-indentation.patch - Bug 2 fix, -p1 against master
gen.txt - gen.bas - self-contained reproducer generator, no includes (I had to change the name to gen.txt because github does not allow attaching .bas files)
(Full disclosure: I had my ai track down the source of this bug but that does not diminish the findings)
Bug 1 — ir-hlc.bas accumulates the emitted C in a STRING, making emission O(n²)
fb_StrConcatAssign() calls fb_hStrRealloc( dst, dst_len+src_len, TRUE ), and fb_hStrRealloc() (src/rtlib/str_core.c:97) over-allocates by only 12.5 %:
12.5 % headroom on a multi-megabyte block, on a heap already holding the whole symbol table and AST, means realloc() cannot extend in place and copies the buffer. The result is Θ(n²) bytes memcpy'd over the emission of an n-byte listing.
Instrumenting sectionWriteLine() on an 11.8 MB listing: 308,130 calls, 10.6 MB of text written, 19.6 s spent inside that one sub out of a 31.5 s run. The mean .text length at append time was 116 KB, so the appends alone moved ≈ 35 GB.
Bug 2 — fbc passes -Wall to gcc without -Wno-misleading-indentation, and that warning is quadratic on gcc < 10
On gcc 9.3 that warning is quadratic in the size of the translation unit — it resolves source lines through the front end's line cache, and on a large file the repeated non-monotonic lookups degrade badly.
Note: These problems exist on fbc compilers even before version 1.20.0
The changes/patches pass all FBC's unit tests.
I have personally experienced my large FB projects dropping from 40+ seconds to 3.5 seconds compile times.
Attachments:
REPORT.md - the actual bug report
0001-ir-hlc-section-buffer.patch - Bug 1 fix, -p1 against master
0002-gcc-wno-misleading-indentation.patch - Bug 2 fix, -p1 against master
gen.txt - gen.bas - self-contained reproducer generator, no includes (I had to change the name to gen.txt because github does not allow attaching .bas files)
(Full disclosure: I had my ai track down the source of this bug but that does not diminish the findings)