Z machine memory usage, in exact bytes?

Question: I’m trying to shrink the memory footprint of an extension, so I compile two versions of it, Plan A and Plan B. I compare the sizes of the resulting .z8 files using the command line, but they’re the exact same number of bytes for both plans! What the hey? I thought it was my filesystem playing tricks on me, but Windows and Mac both do this. But the resulting sizes cannot be the same. In one case I turned a single-column I7 table into an I6 array. The array method should be smaller – it lacks header bytes, lacks a parallel “blanks” array, lacks a lot of auto-created debugging information, etc. But the .z8 filesizes per the “ls” or “dir” command are precisely equal.

What am I missing? Is there maybe an interpreter that can give me some details about what’s going on here?

Is it possible that all the extra memory usage happens at runtime? There was something about that in the last discussion of measuring memory usage, and the result was a uservoice suggestion for a runtime memory report command.

Header address $0e well tell you exactly how much dynamic memory is used. I suspect Inform 7 is making up the reduction with something else, maybe a larger heap for example.

Z-machine files are rounded up in size to the nearest 512 bytes. (Infocom did this to make their page-swapping interpreters easier to write. Actually I’m not sure Infocom always did it, but I6 always does.) (In Glulx, I made all the memory boundaries multiples of 256, for simplicity and in case anyone cared.)

No, for Z-code that’s impossible. The compiler pre-allocates a large buffer and that’s it.

If you want to know the memory layout in more detail, re-run the I6 compiler on auto.inf and include the “-z” flag. It’s not super-explicit, but it shows how much memory goes to array data, object properties, and a few other categories.

Thanks zarf, I’ve give it a whirl.

That’s good to know… I’m going to attempt to bookmark this discussion.

For posterity (and in case I lose it) this is what I entered in the DOS prompt and got back. Know that the switches are “p” for percentages (the final part), “s” for statistics (the first part), “w” to not print those 1400 warning messages, and “z” for the pretty map.

[code]
C:\Program Files\Inform 7\Compilers>inform-631.exe -pswz “c:\Documents and Settings\ron\My Documents\Inform\Projects\CLM\custom lib msg.inform\Build\auto.inf”

Inform 6.31N for Win32 (22nd April 2010)
In: 1 source code files 31010 syntactic lines
36738 textual lines 1364903 characters (ISO 8859-1 Latin1)
Allocated:
5268 symbols (maximum 20000) 2674600 bytes of memory
Out: Version 5 “Advanced” story file 1.110323 (203K long):
21 classes (maximum 200) 42 objects (maximum 639)
208 global vars (maximum 233) 13946 variable/array space (maximum 180000)
84 verbs (maximum 255) 313 dictionary entries (maximum 2000)
153 grammar lines (version 2) 239 grammar tokens (unlimited)
81 actions (maximum 200) 36 attributes (maximum 48)
38 common props (maximum 62) 17 individual props (unlimited)
52498 characters used in text 40486 bytes compressed (rate 0.771)
0 abbreviations (maximum 64) 1643 routines (unlimited)
34471 instructions of Z-code 19179 sequence points
22748 bytes readable memory used (maximum 65536)
207624 bytes used in Z-machine 54520 bytes free in Z-machine
Dynamic ±--------------------+ 00000
memory | header |
±--------------------+ 00040
| abbreviations |
+ - - - - - - - - - - + 00042
| abbreviations table |
±--------------------+ 00102
| header extension |
±--------------------+ 0010a
| property defaults |
+ - - - - - - - - - - + 00188
| objects |
+ - - - - - - - - - - + 003d4
| object short names, |
| common prop values |
+ - - - - - - - - - - + 00a88
| class numbers table |
+ - - - - - - - - - - + 00ab4
| symbol names table |
+ - - - - - - - - - - + 00e82
| indiv prop values |
±--------------------+ 0111e
| global variables |
+ - - - - - - - - - - + 012fe
| arrays |
+=====================+ 04799
Readable| grammar table |
memory + - - - - - - - - - - + 04d2d
| actions |
+ - - - - - - - - - - + 04dcf
| parsing routines |
+ - - - - - - - - - - + 04dd1
| adjectives |
±--------------------+ 04dd1
| dictionary |
+=====================+ 058dc
Above | Z-code |
readable±--------------------+ 2adc8
memory | strings |
±--------------------+ 32b08
Approximate percentage breakdown of story file:
Z-code 73.6%
Static strings 15.4%
Dictionary 1.3%
Objects 1.9%
Globals 6.7%
Parsing tables 0.7%
Header and synonyms 0.1%
Total of save area 8.8%
Total of text 19.4%
Compiled with 1491 suppressed warnings
Completed in 0 seconds

C:\Program Files\Inform 7\Compilers>[/code]

And my fabulous results:

The I7 table produces a smaller Z8 file than an I6 array.

:open_mouth:

The details, straight from the UNIX prompt’s mouth:

~/Desktop> inform-6.32-biplatform -pszw withI6array.inf > aboutI6array.txt ~/Desktop> inform-6.32-biplatform -pszw withI7table.inf > aboutI7table.txt ~/Desktop> diff aboutI6array.txt aboutI7table.txt In: 1 source code files 30756 syntactic lines | In: 1 source code files 30791 syntactic lines 38134 textual lines 1354919 characters (ISO 8 | 38180 textual lines 1356447 characters (ISO 8 5223 symbols (maximum 20000) 2643464 bytes of memory | 5252 symbols (maximum 20000) 2643655 bytes of memory 208 global vars (maximum 233) 13936 variable/array spa | 208 global vars (maximum 233) 13953 variable/array spa 52136 characters used in text 40172 bytes compressed ( | 52121 characters used in text 40162 bytes compressed ( 33972 instructions of Z-code 18965 sequence points | 33967 instructions of Z-code 18970 sequence points 22664 bytes readable memory used (maximum 65536) | 22684 bytes readable memory used (maximum 65536) 205164 bytes used in Z-machine 56980 bytes free in Z-ma | 205136 bytes used in Z-machine 57008 bytes free in Z-ma + - - - - - - - - - - + 00e7e | + - - - - - - - - - - + 00e80 +---------------------+ 01113 | +---------------------+ 01115 + - - - - - - - - - - + 012f3 | + - - - - - - - - - - + 012f5 +=====================+ 04784 | +=====================+ 04797 memory + - - - - - - - - - - + 04cf7 | memory + - - - - - - - - - - + 04d0a + - - - - - - - - - - + 04d99 | + - - - - - - - - - - + 04dac + - - - - - - - - - - + 04d9b | + - - - - - - - - - - + 04dae +---------------------+ 04d9b | +---------------------+ 04dae +=====================+ 05888 | +=====================+ 0589c readable+---------------------+ 2a4e0 | readable+---------------------+ 2a4e8 +---------------------+ 3216c | +---------------------+ 32150 Globals 6.7% | Globals 6.8% Compiled with 1487 suppressed warnings | Compiled with 1488 suppressed warnings

I tried with the Release versions of both, and got similar results. I would’ve expected the I7 version to shrink some in that case anyway, but it didn’t. Presumably the Use Memory Economy option would’ve removed the ability to print table names, maybe?

After further digging, I think I did find out why the I7 was smaller than the I6. Observe the I6 code, which is just part of the extension:[code]To decide which text is the pronoun corresponding to (decl - a declension) in (gcase - a grammatical case): (- CorrespondingPronoun({gcase} + {decl}) -).

Include (-
[ CorrespondingPronoun decl_case;
(+ the prior named noun +) = nothing;
return declensions–>(decl_case - 1);
];

Array declensions --> “I” “you” “he” “she” “it” “we” “you” “they” “me” “you” “him” “her” “it” “us” “you” “them” “mine” “yours” “his” “hers” “its” “ours” “yours” “theirs” “myself” “yourself” “himself” “herself” “itself” “ourselves” “yourselves” “themselves” “my” “your” “his” “her” “its” “our” “your” “their”; -).[/code]
It’s the strings. I7, when finding a piece of text that’s identical to another piece of text, will include it only once and have both places point to it with a name like SC_178. When the text is included via I6 inclusion like the above, it cannot do this, so loses the opportunity to merge them. When I changed the array to numbers, I got more sensible results.

~/Desktop> inform-6.32-biplatform -pszw withI6arrayNums.inf > aboutI6arrayNums.txt ~/Desktop> inform-6.32-biplatform -pszw withI7tableNums.inf > aboutI7tableNums.txt ~/Desktop> diff aboutI6arrayNums.txt aboutI7tableNums.txt In: 1 source code files 30756 syntactic lines | In: 1 source code files 30765 syntactic lines 38134 textual lines 1354695 characters (ISO 8 | 38153 textual lines 1355426 characters (ISO 8 5223 symbols (maximum 20000) 2643446 bytes of memory | 5224 symbols (maximum 20000) 2643468 bytes of memory 208 global vars (maximum 233) 13918 variable/array spa | 208 global vars (maximum 233) 13934 variable/array spa 51970 characters used in text 40038 bytes compressed ( | 51994 characters used in text 40060 bytes compressed ( 33972 instructions of Z-code 18965 sequence points | 33969 instructions of Z-code 18971 sequence points 22648 bytes readable memory used (maximum 65536) | 22664 bytes readable memory used (maximum 65536) 204964 bytes used in Z-machine 57180 bytes free in Z-ma | 204984 bytes used in Z-machine 57160 bytes free in Z-ma + - - - - - - - - - - + 00e7e | + - - - - - - - - - - + 00e80 +---------------------+ 01113 | +---------------------+ 01115 + - - - - - - - - - - + 012f3 | + - - - - - - - - - - + 012f5 +=====================+ 04772 | +=====================+ 04784 memory + - - - - - - - - - - + 04ce5 | memory + - - - - - - - - - - + 04cf7 + - - - - - - - - - - + 04d87 | + - - - - - - - - - - + 04d99 + - - - - - - - - - - + 04d89 | + - - - - - - - - - - + 04d9b +---------------------+ 04d89 | +---------------------+ 04d9b +=====================+ 05878 | +=====================+ 05888 readable+---------------------+ 2a4d0 | readable+---------------------+ 2a4d8 +---------------------+ 320a4 | +---------------------+ 320b8 Compiled with 1487 suppressed warnings | Compiled with 1488 suppressed warnings

If you want strings in your I6 to be interned, you can always use (+ +): Array declensions --> (+ "I" +) (+ "you" +) (+ "he" +) (+ "she" +) (+ "it" +) (+ "we" +) (+ "you" +) (+ "they" +) (+ "me" +) (+ "you" +) (+ "him" +) (+ "her" +) (+ "it" +) (+ "us" +) (+ "you" +) (+ "them" +) (+ "mine" +) (+ "yours" +) (+ "his" +) (+ "hers" +) (+ "its" +) (+ "ours" +) (+ "yours" +) (+ "theirs" +) (+ "myself" +) (+ "yourself" +) (+ "himself" +) (+ "herself" +) (+ "itself" +) (+ "ourselves" +) (+ "yourselves" +) (+ "themselves" +) (+ "my" +) (+ "your" +) (+ "his" +) (+ "her" +) (+ "its" +) (+ "our" +) (+ "your" +) (+ "their" +);

Oh very nice, EmacsUser. Thank you.