Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use arena allocator for large arrays #88

Open
SiebrenW opened this issue Oct 26, 2024 · 0 comments
Open

Use arena allocator for large arrays #88

SiebrenW opened this issue Oct 26, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@SiebrenW
Copy link
Contributor

Describe the problem

In the ISO15118 -2 and -20 some arrays have become increasingly large (ie: signatures, certs, schedules) making it harder to keep on the stack with another application running on top of it, especially on some embedded devices.

The issue lies in that these blocks need to be pre-allocated in a single uber-struct with everything in it, even if not all elements are filled (full cert with a full schedules of all kinds). We are forced to pay for what we don't use.

Describe your solution

Ideally an arena allocator may be used with the exi stream that will only make room for the elements that are required.

ie:

struct myArrayNode {
  MyEnormousDatatype data;
  myArrayNode* next;
};
struct MyType {
  myArrayNode* myArray;
}
struct exi_steam {
  uint8_t *data;
  size_t data_position;
  uint8_t byte_pos;
  uint8_t *allocated;
  size_t alloc_pos;
};
int decodeMyType(struct exi_stream* stream, MyType* output) {
// add item
  err = arena_alloc(stream, sizeof(*output->myArray), &output->myArray);
  //...
  err = decode_MyEnormousDatatype(stream, &output->myArray.data);
  // or with a helper macro/function
  MyEnormousDatatype* item = NULL;
  err = arena_alloc_next(stream, *item, sizeof(*output->myArray), &output->myArray);
  err = decode_MyEnormousDatatype(stream, item);
}

at the end of the decode the stream will contain the allocator of the message, so you can't simply empty it if you still need it. I do think this is worth the tradeoff though.

Alternatively an allocator for a specific field may be used:

struct MyType {
  myArrayNode* myArray;
  uint8_t* myArray_allocator;
  size_t myArray_alloc_size;
}

Then the user would have to set this before starting decoding:

ExiDocument_foo foo;
uint8_t data[200];
foo.myMessage.myArray_allocator = data;
foo.myMessage.myArray_alloc_size = sizeof(data);
decode_Document_foo(stream, &foo);

But then we can't clear data with a simple memset anymore.

Additional context

This also makes it easier to "ignore" out of range items without throwing an error. You can keep decoding until you reach the end of the list, you're "just" missing the later items, which may be better than error out the charging session if it's not an important part, though I suspect this won't have many other usecases outside of an underpowered microcontroller.

In scenarios where few EVs use all elements of these arrays this can have a much smaller footprint and the allocator can be decreased, making up more resources for the rest of the system.

@SiebrenW SiebrenW added the enhancement New feature or request label Oct 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant