Use our new space-optimization feature to reduce your code's footprint; it signficantly reduces the amount of code generated, thereby reducing the size of your binaries.
With the space-optimization feature, encoding, decoding, and the freeing of memory are table-driven, rather than function-based. Instead of generating an encode, decode, and free function for every type contained in your ASN.1 schema, we generate data tables. These tables provide information about your ASN.1 types: what components make up constructed types, how the types are represented in C, and information relevant to their PER encoding. Given an ASN.1 type, the tables provide everything the encode, decode, and free engines need to do their jobs.
Note
This feature is only supported for C and for unaligned PER.
How much space can you save?
To get an idea of the potential savings, we compared the overall size of a simple executable, with and without the space-optimization feature, as well as the size of the object files related to encoding, decoding and memory freeing, with and without the feature. This gives you an idea of the savings in the context of an executable (where the linked libraries impact the overall size), as well as the savings for just the parts actually being swapped (i.e. the table data versus the functional code).
For this comparison, we generated code for the 3GPP LTE NR RRC specification.
A few quick notes:
- Binaries were statically linked with our unlimited (i.e. no license checking), optimized, compact runtime libraries.
- Code was compiled with Visual Studio 2022, using /O1.
Overall executable size comparision:
| Executable does | size w/o SO | size w/SO | % space saved |
|---|---|---|---|
| encoding only | 1684992 | 885760 | 47 |
| decoding only | 1995264 | 946688 | 53 |
| encoding, decoding, and free | 3598848 | 977920 | 73 |
Object file size comparision for table source (SO) vs. functional source (not SO), for encoding, decoding, and free:
| including code for | functional code size | table code (SO) size | % space saved |
|---|---|---|---|
| encode, decode, free | 7697287 | 48803 | 99 |
| encode only | 2770034 | 48803 | 98 |
| decode only | 3065277 | 48803 | 98 |
Switching between space-optimized and non-space-optimized
For new work, it's easy to switch between using and not using the space-optimization feature. For existing work, you might have to change some command line options, and that might require changes to your code. Here are the things to know:
- Either way, the same types are generated.
- Either way, the same PER encode, decode, and free functions are generated, except that in the space-optimized case, they are actually macros.
- The space-optimization option requires using certain command line arguments. If you aren't already using those arguments and you switch to space-optimized, you may have to adjust some of your code to account for differences due to those arguments. For example, -dynamic is required, and that changes some non-pointer types into pointer types that must point to dynamically allocated memory.
Limitations
The main limitations to be aware of are:
- Only C and unaligned PER are supported.
- Constraints are not enforced, outside of limitations imposed by the schema-informed nature of PER. For example, INTEGER(0..6) is encoded in 4 bits. The value 7 does not satisfy the constraint, but it will be accepted because it can be encoded in 4 bits.
- Table constraints are ignored.
- Data for unknown extension additions will be discarded by decoders and cannot be encoded by encoders.
- There are various limitations on the schema (e.g. size constraint bounds). These are documented in the manual, but the compiler should tell you if your schema is not supported.
Any Disadvantages?
Besides the limitations above, using space-optimized code is a space-time tradeoff. Your code will use much less space, but it will also run slower. Of course, even if your application's execution time is important, how much this will impact your application overall depends on how much of your overall processing consists of encoding/decoding ASN.1 data. To help give you an idea of the potential impact, we took some measurements. Our technique used the Windows Profiling API (QueryPerformanceCounter) to measure each operation individually, and then we took the average over 10,000 invocations. The time measurements are in microseconds. We linked and built our test application as described above, for analyzing the binary code size.
For a 2348-byte UE-NR-Capability message, we had the following results:
| operation | avg w/o SO | avg w/SO | multiplier |
|---|---|---|---|
| decode | 71.23 | 128.62 | 1.8x |
| encode | 33.69 | 125.05 | 3.7x |
| free | 11.05 | 55.95 | 5.1x |
For a 111-byte SIB4 message, we had the following results:
| operation | avg w/o SO | avg w/SO | multiplier |
|---|---|---|---|
| decode | 2.23 | 3.89 | 1.7x |
| encode | 1.02 | 4.17 | 4.1x |
| free | .27 | 1.28 | 4.7x |
For More Information
For more information, refer to the manual.