source: tests/collections/string-gc.cfa@ b28ce93

Last change on this file since b28ce93 was 3f631d6, checked in by Michael Brooks <mlbrooks@…>, 6 months ago

Switch string io to be generic upon iostream, rather than specific upon fstream.

No direct test added because we currently lack a second implementation of the abstract streams.

Benefit is removing polymorphism-induced noise from cost calculations, in upcoming string-overload reorganizations.

The change in tests 'collections/string-operator*' shows cases where we stopped picking string for the wrong reason. (If we should be picking string for a better reason, that's just ahead.)

  • Property mode set to 100644
File size: 4.2 KB
Line 
1#include <string_res.hfa>
2#include <fstream.hfa>
3
4size_t bytesRemaining() {
5 return DEBUG_string_bytes_avail_until_gc( DEBUG_string_heap() );
6}
7
8size_t heapOffsetStart( string_res & s ) {
9 const char * startByte = DEBUG_string_heap_start( DEBUG_string_heap() );
10 assert( s.Handle.s >= startByte );
11 return s.Handle.s - startByte;
12}
13
14void prtStrRep(const char * label, string_res & s) {
15 sout | label | "from" | heapOffsetStart(s) | "to" | (heapOffsetStart(s) + len(s));
16}
17#define PRT_STR_REP(s) prtStrRep( #s, s )
18
19void basicFillCompact() {
20 sout | "======================== basicFillCompact";
21 string_res xinit = "hello!";
22 string_res x = {xinit, COPY_VALUE};
23 string_res padder = "----|";
24 sout | x;
25 for( 3 ) {
26 x += padder;
27 sout | x;
28 }
29
30 // x and padder overlap
31 sout | "--A";
32 sout | "length of x:" | len(x);
33 PRT_STR_REP(padder);
34 PRT_STR_REP(x);
35
36 while ( bytesRemaining() + 1 > 5 ) { // until room for "q" but not another "----|" thereafter
37 x += padder;
38 }
39
40 // x and padder still overlap; now x is huge
41 sout | "--B";
42 sout | "length of x:" | len(x);
43 PRT_STR_REP(padder);
44 PRT_STR_REP(x);
45
46 assert( bytesRemaining() >= 1 );
47 x = "q";
48
49 // x and padder no longer overlap; baseline xinit
50 sout | "--C";
51 PRT_STR_REP(xinit);
52 PRT_STR_REP(padder);
53 PRT_STR_REP(x);
54
55 // want the next edit to straddle the bound
56 assert( bytesRemaining() < len(padder) );
57
58 sout | "--D";
59 sout | "before append, x = " | x; // q
60 x += padder; // trigger compaction
61 sout | "after append, x = " | x; // q----|
62
63 // x and padder moved to the start
64 sout | "--E";
65 PRT_STR_REP(xinit);
66 PRT_STR_REP(padder);
67 PRT_STR_REP(x);
68
69 // plenty of room now
70 sout | "--F";
71 sout | bytesRemaining() | "bytes available before re-fill";
72
73 // fill it again
74 string_res z = "zzz";
75 while ( bytesRemaining() > 1 ) {
76 z += ".";
77 }
78
79 sout | bytesRemaining() | "bytes available after re-fill";
80
81 // ensure not affected (shows it's not referencing an invalid location that hadn't been overwritten from the original value yet)
82 // black-box criterion that matches earlier "saw it move"
83 sout | "--G";
84 sout | "after re-fill, x = " | x; // q----|
85
86 // leave the heap basically empty, for the next test
87 z = ""; // turn used space into gargbage
88 string_res whatever = "asdf"; // trigger compaction
89 assert( bytesRemaining() > 100 );
90}
91
92void fillCompact_withSharedEdits() {
93 // do an assignment that causes a collection to happen, while there are edits shared (substrings)
94
95 sout | "======================== fillCompact_withSharedEdits";
96
97 // mostly fill the pad
98 string_res z = "zzz";
99 while ( bytesRemaining() > 10 ) {
100 z += ".";
101 }
102 z = ""; // leave compaction possible
103
104 // setup
105 string_res x = "hello";
106 string_res y = { x, SHARE_EDITS, 0, 5 };
107 PRT_STR_REP(x);
108 PRT_STR_REP(y);
109 sout | "-";
110
111 sout | "before reassign, x = " | x; // hello
112 sout | "before reassign, y = " | y; // hello
113
114 x = "0123456789"; // compact here
115
116 sout | "after reassign, x = " | x; // 0123456789
117 sout | "after reassign, y = " | y; // 0123456789
118
119 PRT_STR_REP(x);
120 PRT_STR_REP(y);
121}
122
123void fillNoCompact() {
124 // show that allocating in a heap filled with mostly live strings (no collectable garbage) causes heap growth
125
126 sout | "======================== fillNoCompact";
127
128 size_t lastTimeBytesAvail = bytesRemaining();
129 assert( lastTimeBytesAvail >= 200 ); // starting this test with nontrivial room
130
131 // mostly fill the pad
132 string_res a = "aaa"; // will have to be moved
133 string_res z = "zzz";
134 for (i; 5) {
135 while ( bytesRemaining() > 10 ) {
136 z += ".";
137 }
138 sout | "about to expand, a = " | a;
139 while ( bytesRemaining() <= 10 ) {
140 z += ".";
141 }
142 sout | "expanded, a = " | a;
143
144 // each growth gives more usable space than the last
145 assert( bytesRemaining() > lastTimeBytesAvail );
146 lastTimeBytesAvail = bytesRemaining();
147 }
148}
149
150int main() {
151 basicFillCompact();
152 fillCompact_withSharedEdits();
153 fillNoCompact();
154}
Note: See TracBrowser for help on using the repository browser.