EVerest / EVerest/cbexigen

Use arena allocator for large arrays

Open
#88 4 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
69
Forks
36
Avg merge
3h 30m
Merged PRs (30d)
1

Description

### 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:

```cpp
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:

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

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

```cpp
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.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.