Skip to content

Commit 87bfb79

Browse files
committed
Pack the complete API v2 descriptor graph
Replace late-bound descriptor procedures with validated, offset-based schema and complex metadata images. Use an explicit per-load context for reentrant module construction while retaining the version 1 compatibility path. AP242e4 generated output falls from 9,060,249 to 4,865,657 bytes and clean compile/link time falls from 41.49 to 18.71 seconds. The schema DSO falls from 7,470,304 to 3,503,352 bytes and ELF relocations fall from 33,221 to 9,620.
1 parent 43a95a6 commit 87bfb79

16 files changed

Lines changed: 2392 additions & 111 deletions

doc/ap242-v2-benchmarks.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,39 @@ classes remain unchanged.
116116
The complete exchange-file check again created and validated 10,609
117117
instances with zero errors and zero warnings. Its 949,685-byte rewrite
118118
differed from recommendation 5 only in the expected `FILE_NAME` timestamp.
119+
120+
## Recommendation 7
121+
122+
This stage replaces the remaining generated descriptor procedures with one
123+
bounded, offset-based schema image. The shared loader validates every array,
124+
string, range, descriptor reference, schema binding, and complex-entity tree
125+
before it changes the registry. It then constructs the descriptor graph with
126+
an explicit per-load context; the process-global capture path remains only for
127+
older generated API v2 code. Complex-entity metadata uses the same packed
128+
representation and validation model.
129+
130+
Source and binary measurements compare recommendation 6 with the complete
131+
descriptor image. Compile times use clean CMake builds with two compiler
132+
processes. Read/write times use matching 20-run batches.
133+
134+
| Measurement | Recommendation 6 | Recommendation 7 | Change |
135+
|---|---:|---:|---:|
136+
| Generated files | 905 | 865 | -4.4% |
137+
| Generated lines | 117,046 | 86,400 | -26.2% |
138+
| Generated bytes | 9,060,249 | 4,865,657 | -46.3% |
139+
| Entity initialization chunks | 38 | 0 | -100.0% |
140+
| Compile/link wall time | 41.49 s | 18.71 s | -54.9% |
141+
| Compile/link peak RSS | 208,188 KiB | 208,528 KiB | +0.2% |
142+
| Schema shared library | 7,470,304 B | 3,503,352 B | -53.1% |
143+
| ELF relocations | 33,221 | 9,620 | -71.0% |
144+
| 20 full read/write runs | 5.07 s | 4.97 s | -2.0% |
145+
| Full read/write peak RSS | 85,572 KiB | 82,916 KiB | -3.1% |
146+
147+
The image removes the 2,407 generated entity initialization functions and
148+
23,601 additional relocations. The generated schema library is 3,966,952
149+
bytes smaller, while its existing typed SELECT and enumeration factories
150+
remain available for this transitional stage.
151+
152+
The complete exchange-file check created and validated 10,609 instances with
153+
zero errors and zero warnings. Its 949,685-byte rewrite retained the same
154+
semantic result as recommendation 6.

include/clstepcore/schemaInit.h

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "clstepcore/entityDescriptor.h"
1111
#include "clstepcore/enumTypeDescriptor.h"
1212
#include "clstepcore/selectTypeDescriptor.h"
13+
#include "clstepcore/schemaModule.h"
1314

1415
class Derived_attribute;
1516
class Inverse_attribute;
@@ -148,6 +149,179 @@ struct SC_CORE_EXPORT GlobalRuleInitRecord {
148149
const char * text;
149150
};
150151

152+
enum SchemaImageDescriptorRefKind {
153+
SchemaImageRef_None,
154+
SchemaImageRef_Entity,
155+
SchemaImageRef_Type,
156+
SchemaImageRef_Builtin,
157+
SchemaImageRef_Aggregate
158+
};
159+
160+
struct SC_CORE_EXPORT SchemaImageDescriptorRef {
161+
uint32_t kind;
162+
uint32_t schema;
163+
uint32_t index;
164+
};
165+
166+
struct SC_CORE_EXPORT SchemaImageSchemaRecord {
167+
uint32_t name;
168+
uint32_t firstEntity;
169+
uint32_t entityCount;
170+
uint32_t firstType;
171+
uint32_t typeCount;
172+
};
173+
174+
struct SC_CORE_EXPORT SchemaImageEntityRecord {
175+
uint32_t schema;
176+
uint32_t name;
177+
uint32_t flags;
178+
uint32_t supertypeStatement;
179+
uint32_t firstSupertype;
180+
uint32_t supertypeCount;
181+
uint32_t firstAttribute;
182+
uint32_t attributeCount;
183+
uint32_t firstWhereRule;
184+
uint32_t whereRuleCount;
185+
uint32_t firstUniqueRule;
186+
uint32_t uniqueRuleCount;
187+
};
188+
189+
enum SchemaImageEntityFlags {
190+
SchemaImageEntity_Abstract = 1u << 0,
191+
SchemaImageEntity_ExternalMapping = 1u << 1
192+
};
193+
194+
struct SC_CORE_EXPORT SchemaImageTypeRecord {
195+
uint32_t schema;
196+
uint32_t name;
197+
uint32_t description;
198+
uint32_t fundamentalType;
199+
uint32_t descriptorKind;
200+
int32_t uniqueElements;
201+
SchemaImageDescriptorRef referent;
202+
uint32_t aggregate;
203+
uint32_t firstSelectElement;
204+
uint32_t selectElementCount;
205+
uint32_t firstWhereRule;
206+
uint32_t whereRuleCount;
207+
uint32_t firstEnumElement;
208+
uint32_t enumElementCount;
209+
};
210+
211+
struct SC_CORE_EXPORT SchemaImageAttributeRecord {
212+
uint32_t name;
213+
SchemaImageDescriptorRef domain;
214+
uint32_t optional;
215+
uint32_t unique;
216+
uint32_t attrType;
217+
uint32_t initializer;
218+
uint32_t invertedAttribute;
219+
uint32_t invertedEntity;
220+
};
221+
222+
struct SC_CORE_EXPORT SchemaImageAggregateRecord {
223+
uint32_t schema;
224+
uint32_t description;
225+
uint32_t fundamentalType;
226+
SchemaImageDescriptorRef referent;
227+
uint32_t bound1Type;
228+
int32_t bound1;
229+
uint32_t bound1Text;
230+
uint32_t bound2Type;
231+
int32_t bound2;
232+
uint32_t bound2Text;
233+
uint32_t optionalElements;
234+
uint32_t uniqueElements;
235+
};
236+
237+
struct SC_CORE_EXPORT SchemaImageRuleRecord {
238+
uint32_t text;
239+
};
240+
241+
enum SchemaImageSchemaTextKind {
242+
SchemaImageText_GlobalRule,
243+
SchemaImageText_Function,
244+
SchemaImageText_Procedure
245+
};
246+
247+
struct SC_CORE_EXPORT SchemaImageSchemaTextRecord {
248+
uint32_t schema;
249+
uint32_t kind;
250+
uint32_t name;
251+
uint32_t text;
252+
};
253+
254+
struct SC_CORE_EXPORT SchemaImageSchemaBinding {
255+
Schema ** schemaSlot;
256+
ModelContentsCreator modelContentsCreator;
257+
SchemaModule * module;
258+
};
259+
260+
struct SC_CORE_EXPORT SchemaImageTypeBinding {
261+
void * slot;
262+
SelectCreator selectCreator;
263+
EnumCreator enumCreator;
264+
AggregateCreator aggregateCreator;
265+
};
266+
267+
enum SchemaLoadError {
268+
SchemaLoad_Ok,
269+
SchemaLoad_UnsupportedVersion,
270+
SchemaLoad_TruncatedImage,
271+
SchemaLoad_InvalidOffset,
272+
SchemaLoad_InvalidString,
273+
SchemaLoad_InvalidReference,
274+
SchemaLoad_CountMismatch,
275+
SchemaLoad_MissingBinding,
276+
SchemaLoad_ModuleFailure
277+
};
278+
279+
struct SC_CORE_EXPORT SchemaLoadResult {
280+
SchemaLoadError error;
281+
uint32_t record;
282+
283+
bool Succeeded() const {
284+
return error == SchemaLoad_Ok;
285+
}
286+
const char * Message() const;
287+
};
288+
289+
SC_CORE_EXPORT SchemaLoadResult InitializeSchemaFromImage(
290+
Registry & registry, const SchemaModuleImage & image,
291+
const SchemaImageSchemaBinding * schemaBindings,
292+
size_t schemaBindingCount,
293+
const SchemaImageTypeBinding * typeBindings,
294+
size_t typeBindingCount, SchemaLoadContext & context );
295+
296+
enum PackedComplexImageVersion {
297+
PackedComplexImageVersion_1 = 1
298+
};
299+
300+
struct SC_CORE_EXPORT PackedComplexImage {
301+
uint32_t version;
302+
uint32_t byteSize;
303+
uint32_t stringOffset;
304+
uint32_t stringBytes;
305+
uint32_t nodeOffset;
306+
uint32_t nodeCount;
307+
uint32_t listOffset;
308+
uint32_t listCount;
309+
};
310+
311+
struct SC_CORE_EXPORT PackedComplexNode {
312+
uint32_t kind;
313+
uint32_t name;
314+
uint32_t firstChild;
315+
uint32_t nextSibling;
316+
};
317+
318+
struct SC_CORE_EXPORT PackedComplexList {
319+
uint32_t rootNode;
320+
};
321+
322+
SC_CORE_EXPORT ComplexCollect * InitializePackedComplexSupport(
323+
const PackedComplexImage & image, SchemaLoadResult * result = 0 );
324+
151325
SC_CORE_EXPORT void InitializeSchemas( Registry & reg,
152326
const SchemaInitRecord * records,
153327
size_t count );

include/clstepcore/schemaModule.h

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,77 @@ struct SC_CORE_EXPORT SchemaModuleSlot {
3333
};
3434

3535
enum SchemaModuleImageVersion {
36-
SchemaModuleImageVersion_1 = 1
36+
SchemaModuleImageVersion_1 = 1,
37+
SchemaModuleImageVersion_2 = 2
38+
};
39+
40+
enum SchemaModuleImageFlags {
41+
SchemaModuleImage_FullMetadata = 0,
42+
SchemaModuleImage_StructuralMetadata = 1u << 0
3743
};
3844

3945
/**
4046
* Relocation-free generated header for a schema module image.
4147
*
42-
* Descriptor initialization helpers record entities, types, and attributes
43-
* in stable generated-ID order. The image therefore needs only a version
44-
* and counts rather than one relocated pointer per descriptor.
48+
* Version 1 records only stable generated-ID counts. Version 2 describes
49+
* one bounded block of offset-based schemas, descriptors, metadata, and
50+
* strings. Runtime loading validates the complete block before constructing
51+
* descriptors or changing a Registry.
4552
*/
4653
struct SC_CORE_EXPORT SchemaModuleImage {
4754
uint32_t version;
4855
uint32_t entityCount;
4956
uint32_t typeCount;
5057
uint32_t attributeCount;
58+
59+
/* Version 2 fields. Version 1 initializers leave these zero. */
60+
uint32_t byteSize;
61+
uint32_t flags;
62+
uint32_t schemaCount;
63+
uint32_t stringBytes;
64+
uint32_t schemaOffset;
65+
uint32_t entityOffset;
66+
uint32_t typeOffset;
67+
uint32_t attributeOffset;
68+
uint32_t aggregateCount;
69+
uint32_t aggregateOffset;
70+
uint32_t referenceCount;
71+
uint32_t referenceOffset;
72+
uint32_t ruleCount;
73+
uint32_t ruleOffset;
74+
uint32_t schemaTextCount;
75+
uint32_t schemaTextOffset;
76+
uint32_t enumElementCount;
77+
uint32_t enumElementOffset;
78+
uint32_t stringOffset;
79+
uint32_t reserved;
80+
uint64_t fingerprint;
81+
};
82+
83+
class SchemaModule;
84+
85+
/**
86+
* Per-load descriptor collection used by packed API v2 schema images.
87+
*
88+
* Keeping this state explicit makes independent schema loads reentrant and
89+
* avoids the process-global capture map retained for version-1 images.
90+
*/
91+
class SC_CORE_EXPORT SchemaLoadContext {
92+
class Impl;
93+
Impl * _impl;
94+
95+
SchemaLoadContext( const SchemaLoadContext & );
96+
SchemaLoadContext & operator=( const SchemaLoadContext & );
97+
friend class SchemaModule;
98+
99+
public:
100+
SchemaLoadContext();
101+
~SchemaLoadContext();
102+
103+
void Begin( Schema & schema );
104+
void RecordEntity( Schema & schema, const EntityDescriptor * entity );
105+
void RecordType( Schema & schema, const TypeDescriptor * type );
106+
void RecordAttribute( Schema & schema, const AttrDescriptor * attribute );
51107
};
52108

53109
SC_CORE_EXPORT void RecordSchemaModuleEntity(
@@ -75,6 +131,7 @@ class SC_CORE_EXPORT SchemaModule {
75131
std::vector<const EntityDescriptor *> _entities;
76132
std::vector<const TypeDescriptor *> _types;
77133
std::vector<const AttrDescriptor *> _attributes;
134+
uint64_t _fingerprint;
78135
#ifdef _MSC_VER
79136
#pragma warning( pop )
80137
#endif
@@ -95,6 +152,8 @@ class SC_CORE_EXPORT SchemaModule {
95152
const SchemaModuleSlot * attributes, size_t attributeCount );
96153
void InitializeFromImage( Schema & schema,
97154
const SchemaModuleImage & image );
155+
bool InitializeFromContext( Schema & schema, SchemaLoadContext & context,
156+
uint64_t fingerprint );
98157

99158
bool IsInitialized() const;
100159
const Schema & GetSchema() const;
@@ -104,6 +163,7 @@ class SC_CORE_EXPORT SchemaModule {
104163
size_t EntityCount() const;
105164
size_t TypeCount() const;
106165
size_t AttributeCount() const;
166+
uint64_t Fingerprint() const;
107167
};
108168

109169
#endif

0 commit comments

Comments
 (0)