Replies: 6 comments
-
|
We use heap allocated strings because a lot of the events are received as well as sent, so the String either A. has to last as long as it's received event or B. has to be heap allocated. |
Beta Was this translation helpful? Give feedback.
-
Ah, that's the cool thing about |
Beta Was this translation helpful? Give feedback.
-
|
According to
|
Beta Was this translation helpful? Give feedback.
-
Why 32 bytes?That is true. Please correct me if I'm wrong, but I presume that the extra bits come from the fact that Why is this not an issue?A core assumption I am making here is that most usage of Arguably, this has greater implications for memory than the A concrete exampleConsider a situation where we have a string with 10 or so ASCII characters (for the sake of argument). With Now, this is not the case for But in case we do need dynamic allocation, |
Beta Was this translation helpful? Give feedback.
-
|
This could be useful for things such as Embed, or data we send to discord, however models such as |
Beta Was this translation helpful? Give feedback.
-
|
I agree. 👍 Though, it does come with the downside that the API becomes less consistent with strings. I'm not sure how you feel about that from a UX perspective. Personally, I can live with it, but some may argue that we may as well go all-or-nothing here. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Currently, most string fields in the
twilight-modelcrate take in an ownedString. This is fine, but I realize that for most cases, a plain&'static stris sufficient. The mandatory heap allocation (from theString) is thus usually unnecessary. Consider this example with rich embeds (using0.10.2):Hopefully, it is apparent from my example that there are too many
Stringallocations here, where plain&'static strslices will suffice. We can also note theVecallocation, which is arguably unnecessary since we know for certain that there is only one element.1Of course, this example also applies to other areas of the library. Rich embeds are just one particular instance.
A Possible Solution
In line with the goal to reduce heap allocations, I propose that we consider using the
alloc::borrow::Cowsmart pointer instead ofStringandVec. TheCowsmart pointer employs "copy-on-write" semantics so that heap allocations are kept at a minimum.Now, I understand that ownership is one of the primary reasons why
StringandVecwere chosen. After all, it becomes rather cumbersome to use many of the data models if explicit lifetimes were required—though, I personally wouldn't be totally against this proposition.Anyway, a good compromise is to use a
Cow<'static, str>and aCow<'static, [T]>(for all typesT). Observe that the'staticlifetime specifier enforces that the data model (practically) "owns" the slice, even though it is technically borrowed. Therefore, the enclosingstructneed not be generic over arbitrary lifetimes.This gives the user extra flexibility on whether to use a
&'static stror a regularString(e.g. in cases where string interpolation is necessary). Consider the same rich embed example from earlier:It is important to note that there are now zero allocations here. Both the
VecandStringhave been removed in favor of their'staticcounterparts. In case string interpolation or dynamic arrays are needed, one may useCow::Ownedvariant instead (containing the appropriateStringorVec). Consider this other example for mixed usage:Suggestions for Migration
Most builder setters and utilities from this library rely on the fact that the intended target field is a
Stringor aVec. I'm aware that it will be rather tedious to convert all of the parameters to theirCow-equivalent. Luckily, generics come to the rescue! Suppose we intend to migrate to theCowsmart pointer for the builders in thetwilight-utilcrate:The standard library already provides the convenience
FromandIntoimplementations. From the user's perspective, constructing anEmbedFieldBuilderstill works the same as before thanks to the standard conversions.Footnotes
In addition to the heap allocation, extra copies of the data also occur due to the fact that the
String::fromimplementation simply copies the bytes from the&'static strinto the new allocation. TheVecworks in a similar fashion. ↩Beta Was this translation helpful? Give feedback.
All reactions