...
Align | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
Table 3: Collection Types
|
...
An entity type can be marked as transactional. The platform tracks field updates to transactional entities and can rollback changes made to them in the event of an application exception or an explicit rollback. By default, entities and collections are transactional while messages are not. A message can be declared transactional, which is useful in the event that a message is stored as part of an application's state graph.
See State Graph Tree Limitations for some important limitations on the current state graph implementation that may have an impact on state modeling.
...
Code Block | ||||
---|---|---|---|---|
| ||||
@Generated(value="com.neeve.adm.AdmGenerator", date="Fri Jan 23 02:03:22 PST 2015")
public interface IMyMessage extends extends IRogNode, IRogMessage {
//Standard accessors:
public void setMyStringField(final String val);
public String getMyStringField();
//Copying accessors:
public void setMyStringFieldFrom(final XString val);
public void getMyStringFieldTo(final XString val);
public T getMyStringFieldTo(XString.Factory<T> factory);
//Unsafe accessor:
public XString getMyStringFieldUnsafe();
} |
Standard Accessors
The standard accessors are not guaranteed to be zero garbage , and are less efficient because the require encoding of the type into its underlying byte representation.
...
This operation can be dangerous in the presence of object pooling because, if the application erroneously retains a reference to the type, its value will be invalidated when the message is returned to its pool and its backing buffer will be wiped or repurposed. Applications that use this api API should operate with special care and should avoid using this accessor unless performance is of the utmost concern.
...
For arrays it is not possible to distinguish between an empty array or the array not being set. This allows ADM code to operate with protobuf Protobuf encoding under the covers, which is not able to distinguish between an empty or unset array. For this reason, ADM generated code does not generate a hasXXX method for arrays. Setting the code generation property generateArrayGetterEmptyIfNull controls whether an empty or null array is returned when there are no values encoded in the underlying message or entity.
...
The ADM model provides a <types> section that can be used to define types based on the platform's primitive and built-in types. Such semantic types can be used in place of their corresponding primitive type in the model and will inherit their documentation. The type used for the field in generated messages and entities will be the base type specified by the named field.
...
The X Platform provides an XString implementation that allows zero garbage manipulation of Strings. Low latency applications should use XStrings instead of Java Strings in domain state This allows for zero garbage copy of fields to and from outbound and inbound messages and zero garbage manipulation of fields by domain logic. Although the use of XStrings will eliminate garbage, it will not eliminate object promotion across heap generations which can be an expensive operation. To avoid promotions, low latency applications also need the ability to pool and pre-allocate such fields. To make working with such types easier, the ADM model provides support for creating sub types subtypes of XString that are poolable. For String fields that are declared as poolable, the ADM code generator will generate code implementing a new type for the field that is a subtype of XString and the associated classes that allow for the pooling and pre-allocation of fields of this type. All of the methods currently available on XStrings will be available to the subtype. The XString documentation can be found at: http://build.neeveresearch.com/core/javadoc/LATEST/com/neeve/lang/XString.html
...
- The field or type element that defines it has a poolable="true" attribute. The String type will be created based on the name of the field.
- A semantic type is defined with a base type of string and the poolable attribute set to true. The String type will be based on the name of the type.
- For applications that would rather separate the notion of pooling from the model itself, the Code Generator can be run with a directive indicating that all String fields should generate a poolable type (see Directives in the sections below).
- In the future, different narrower directives may be introduced for finer-grained control over what String fields will create poolable types.
...
- A poolable string type cannot be created such that it conflicts with a built-in or primitive type name (string, integer, Currency, etc), nor can the poolable type conflict with a type name used elsewhere within the model (enumerations, entities, messages or collections). In the case where a field name conflicts with one of these types, a semantic type with a different name should be declared to avoid the naming conflict.
...
- None: (Default) With this policy, field names are not suffixed, and it will result in either a code generation or compilation error if a conflict occurs. This policy is useful where the model developer want wants to proactively monitor for such conflicts, and perhaps declare the pooled string field as a semantic type in the <types> section to resolve the conflict.
- Always: With this policy, the pooled string type is always suffixed with String, which greatly reduces the likely hood of a name conflict.
OnConflict: With this policy, the code generator will suffix the generated pooled string type name with 'String' when the name conflicts with another type. For example:
Code Block <enumerations> <enum name="MyEnum"> <const name="Value1" value="1"/> </enum> </enumerations> <fields> <field name="MyEnum" type="String" poolable="true"/> </fields>
would yield a pooled string type of MyEnumString to avoid conflicting with the MyEnum enumeration type.
Note |
---|
Note that usage of OnConflict is unsafe for models that may evolve over time in a fashion that could introduce a field conflict , since it would mean that at such time as a conflict arises, the type name of the pooled string would then be changed and result in compile errors. |
...
Note that for pooled strings, if the length parameter is not specified, the backing buffer size for preallocated Strings will default to 32 bytes. If a length is specified, then that size will be used for the default backing buffer size value for preallocating Strings of that type.
...
- The application can create factories for the generated types to allow application preallocation of the pooled type.
- The generated factory returns unitialized uninitialized XStrings with the option of creating immutable (constant) instances.
- A newly created object will start with an ownership count of 1. The ownership count is used to track an object’s reference count. Users can acquire a pooled object to prevent it from being disposed and cleared. Calling dispose on the type will return it to the pool when the ownership count reaches 0. If the objects returned by the pool will be acquired / disposed across multiple threads, the factory should be created as threaded.
...
Strings from inbound message fields are often stored in domain state. To that end, poolable string types need to be preallocated along with the rest of application to avoid creating new instances at run timeruntime. There are two approaches to handling preallocation:
- Preallocate the pooled string type with preallocated application state, and copy the string from the inbound message into domain state. In this approach, the message keeps its reference to the pooled string field and reuses the same reference when the message is recycled through its pool.
- Use take/lend semantics in the same fashion as with a Nested Entity as described in Xbuf and Embedded Entities. The domain state needn't preallocate the pooled string type , but rather takes if from the message which then draws a new instance from a globally configured preallocated when the message itself is recycled to its pool.
...
Using the static creation methods on a generated pooled type will draw a new instances instance from the generated type's default factory. The default factory is created in the pooled types static initializer block. Therefore, any configuration of the default factory needs to be done before the class is loaded for the values to take effect. Generated Messages draw their values from the default pool. Because messages are themselves pooled, it is not necessarily required that the factory's pool use preallocation to avoid allocating new pooled types at runtime if the application preallocates the strings and copies values out of the message.
...
Default | ||
---|---|---|
<qualifiedClassName>.initialLength | The initial length of the backing buffer to allocate to back the string in serialized form. | taken from length attribute if specified in the model, otherwise 1 |
<qualifiedClassName>.isNative | Whether or not a native backing buffer should be used. This is recommend for performance sensitive apps. | true |
<qualifiedClassName>.pool.enabled | Whether the factory is backed by a pool or if new instances are created on demand. | true |
<qualifiedClassName>.pool.threaded | Whether or not the backing pool is thread-safe. The pool must be thread safe if more than one thread will create strings from this factory, or, crucially, if a separate thread may return the item to the pool. For the default pool this value should almost always be true, because the thread creating the string and the one that ultimately disposed it are usually different. | true |
<qualifiedClassName>.pool.preallocateCount | The number of objects to preallocate, or 0 if no preallocation should be done. Note that preallocation is not done until the class is loaded. | 0 |
...
Depending on the application, it is possible that the Factory need not be threaded if only one thread will be creating Strings from this factory and will never dispose of the strings it creates. If this is the case, then there is no risk that another thread will return the string to the pool and introduce concurrency issues.
...