StringBuilder icon indicating copy to clipboard operation
StringBuilder copied to clipboard

stackalloc-based version

Open SMAH1 opened this issue 1 month ago • 10 comments

I wish you would add a ‍stackalloc-based version in this library to increase performance. Of course, not all existing features will be supported in the proposed version, but the main features like Append, Format, etc. can be implemented (which are commonly used). You may find this link useful.

SMAH1 avatar Nov 01 '25 15:11 SMAH1

Can you elaborate what specific behavior / API you are missing?

new ValueStringBuilder(stackalloc char[256]) is working in this library, just like in the linked article.

linkdotnet avatar Nov 01 '25 17:11 linkdotnet

When I set it manually, I don't want it to enter the 'Rent' phase in case of overflow. That is, in case of overflow, a flag is set and it is not added anymore (subsequent operations are ignored).

Current behavior:

Image

SMAH1 avatar Nov 02 '25 04:11 SMAH1

Interesting - that we could do. I am not sure if we have this as a parameter or an explicit static version like:

using var builder = ValueStringBuilder.CreateStackOnlyNonGrowing(stackalloc char[512]);

The question is what do we do in edge case scenarios like:

using var builder = ValueStringBuilder.CreateStackOnlyNonGrowing(stackalloc char[8]);
builder.Append("1234");

builder.Append("56789");

var output = builder.ToString();

Now, is output 1234 or 12345678? Basically we truncate. I would lean towards the first version if possible as operations are "atomic". As you said, that might lead to special treatment and performance penalties in other areas where we have to know the whole length upfront.

linkdotnet avatar Nov 02 '25 11:11 linkdotnet

On second thought, it will not be a static method, but a new type with maybe limited API. That makes it easier to understand.

linkdotnet avatar Nov 02 '25 15:11 linkdotnet

Why don't we define a parameter in the constructor instead of Static to prevent Growing?

Also, I think that wherever there is an overflow, it should stop writing data and not continue (but not throw an error either, just ignore it).

Also, for this case, I think it would be appropriate if there was a flag indicating this situation (overflow).

SMAH1 avatar Nov 04 '25 04:11 SMAH1

The flag has the issue, that it is non-obvious what happens in edge-cases or functions that might not exist. I do think its own type, would do more justification here.

Especially if you truncate stuff

linkdotnet avatar Nov 04 '25 08:11 linkdotnet

Instead of creating a stackalloc based version, maybe you could create a fixed-size version (maybe 256 chars)? This would allow you to use it outside of ref struct limitations.

This is what I did for my ValueCollections library: https://github.com/Joy-less/ValueCollections?tab=readme-ov-file#valuelist-fixed-size

Joy-less avatar Nov 12 '25 18:11 Joy-less

True - but that would incur allocations.

linkdotnet avatar Nov 12 '25 18:11 linkdotnet

True - but that would incur allocations.

Structs only incur allocations if you heap-allocate them (use them outside ref struct limitations). If you use structs as local variables they are stack-allocated similar to stackalloc. I also believe that when used as fields in classes, they are not boxed separately but stored directly in the class.

Joy-less avatar Nov 12 '25 18:11 Joy-less

I think that depends a bit on the struct layout and stuff, but you might be right - I would need to do more research

linkdotnet avatar Nov 12 '25 18:11 linkdotnet