fix interned string problem with -profiling

This commit is contained in:
Irmen de Jong
2026-02-28 16:19:47 +01:00
parent 2bafc161d6
commit fedf342cee
3 changed files with 28 additions and 1 deletions
+1
View File
@@ -576,6 +576,7 @@ log2_tab
; update the "streaming" crc16 with next byte value
; note: tracks the crc16 checksum in cx16.r15!
; if your code uses that, it must save/restore it before calling this routine
; note: this routine doesn't use a lookup table to speed up the calculation, so it is not particularly fast.
%asm {{
eor cx16.r15H
sta cx16.r15H
@@ -1,11 +1,13 @@
package prog8.compiler.simpleastprocessing
import prog8.code.INTERNED_STRINGS_MODULENAME
import prog8.code.StExtSub
import prog8.code.SymbolTable
import prog8.code.ast.*
import prog8.code.core.DataType
import prog8.code.core.Encoding
import prog8.code.core.IErrorReporter
import prog8.code.source.SourceCode
fun profilingInstrumentation(program: PtProgram, st: SymbolTable, errors: IErrorReporter) {
@@ -13,6 +15,19 @@ fun profilingInstrumentation(program: PtProgram, st: SymbolTable, errors: IError
val instrumentationsToAdd = mutableListOf<Pair<PtNode, PtNode>>()
// make sure there is a block to put interned strings in
val newInternededStringBlock: Boolean
var internedStringsBlock: PtBlock? = program.children.firstOrNull { it is PtBlock && it.name == INTERNED_STRINGS_MODULENAME } as? PtBlock
if(internedStringsBlock==null) {
// there are no interned strings (anymore) so re-insert the block that we need
val options = PtBlock.Options(noSymbolPrefixing = true)
internedStringsBlock = PtBlock(INTERNED_STRINGS_MODULENAME, false, SourceCode.Generated(INTERNED_STRINGS_MODULENAME), options, program.position)
program.add(internedStringsBlock)
newInternededStringBlock = true
} else {
newInternededStringBlock = false
}
walkAst(program) { node, depth ->
when(node) {
is PtSub -> {
@@ -70,6 +85,13 @@ fun profilingInstrumentation(program: PtProgram, st: SymbolTable, errors: IError
}
st.resetCachedFlat()
if(newInternededStringBlock) {
if(internedStringsBlock.children.isEmpty()) {
// no interned strings, remove the block again
program.children.remove(internedStringsBlock)
}
}
}
}
+5 -1
View File
@@ -94,7 +94,7 @@ To use subroutine profiling:
- **Timestamp** (hex): The emulator cycle count when the call was made
- **Routine name**: The fully qualified name of the subroutine (e.g., ``main.start``, ``galaxy.init``)
The file may contain compiler output headers before the actual CSV data starts. The data section begins after a line of dashes (``---``).
The file may contain compiler output headers before the actual CSV data starts. The data section begins after a line of dashes.
Using the parse_profile_csv.py script
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -168,6 +168,9 @@ Here's a typical workflow for profiling a Prog8 program::
The output will show you which routines consume the most time. For example, if a routine shows 49% of total time,
optimizing that routine would have the biggest impact on overall performance.
Make sure to eventually get rid of the profiling code and recompile the program normally without the ``-profiling`` option,
because the logic takes up space and does slow down the actual program a bit.
Tips for effective profiling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -177,6 +180,7 @@ Tips for effective profiling
- A routine with high average time per call may need algorithmic improvements
- Use the flame graph to quickly identify hot paths in the call stack
- Compare profiles before and after optimizations to measure improvement
= **Recompile the program WITHOUT profiling mode after you're done** -- because the profiling logic takes up space and slows down the actual program
Limitations
^^^^^^^^^^^