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

Add InplaceStringBuilder #157

Merged
merged 7 commits into from
Sep 30, 2016
Merged

Add InplaceStringBuilder #157

merged 7 commits into from
Sep 30, 2016

Conversation

pakrym
Copy link

@pakrym pakrym commented Sep 30, 2016

Migrated from: aspnet/HttpAbstractions#717

Added .Build() method for better debugging experience.

Intended to be used instead of pooled StringBuilder or string.Concat when all parts of string are known. (Use cases: aspnet/HttpAbstractions#699, aspnet/HttpAbstractions#716)

Does only 1 allocation of resulting string.

@benaadams @davidfowl @Tratcher @halter73 @rynowak

@pakrym
Copy link
Author

pakrym commented Sep 30, 2016

@benaadams can we keep using Unsafe.CopyBlock as long as it passes the test?

@benaadams
Copy link
Member

That runs Mono also doesn't it? Doesn't look like any platform uses the aligned cpu instructions currently 😁

@benaadams
Copy link
Member

Maybe add a TODO?

{
AppendLength(s.Length);
}
public void AppendLength(char c)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IncrementLength()?

Copy link

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spell check!

}
}

private void EnsureValue(int length)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnsureCapacity?

fixed (char* value = _value)
fixed (char* pDomainToken = s)
{
//TODO: Use CopyBlockUnaligned when added https://github.com/dotnet/corefx/issues/12243

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you file a task for this instead? TODOs are easy to miss

{
if (_writing)
{
throw new InvalidOperationException("Cannot append lenght after write started.");
Copy link

@pranavkm pranavkm Sep 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot append lenght length

}
}

// Debugger calls ToString so this method should be used to get formatted value

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use DebuggerDisplayAttribute to control what gets displayed by the debugger.

IncrementLength(1);
}

public void IncrementLength(int length)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capacity { get; set; }?

Copy link
Author

@pakrym pakrym Sep 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And do Capacity += s.Length?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Seems analogous to StringBuilder in that case

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's different because you are required to IncrementLength for all strings before appending them and I felt like having a method is less error prone then incrementing property.

_length = length;
}

public void IncrementLength(string s)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this + the next one really that useful?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeps the symmetry, if you have char separator would be nice to have

IncrementLength(Key);
IncrementLength(SeperatorChar);
IncrementLength(Value);
Append(Key);
Append(SeperatorChar);
Append(Value);

vs

IncrementLength(Key);
IncrementLength(1); 
IncrementLength(Value);
Append(Key);
Append(SeperatorChar);
Append(Value);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capacity += Key.Length + 1 + Value.Length; is about as pretty :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you can't copy paste it as easily ;)

{
if (_offset != _length)
{
throw new InvalidOperationException($"Entire reserved lenght was not used. Length: '{_length}', written '{_offset}'.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lenght length

}
if (_offset + length > _length)
{
throw new InvalidOperationException($"Not enough space to write '{length}' characters, only '{_length - _offset}' left.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space -> capacity

{
throw new InvalidOperationException($"Entire reserved lenght was not used. Length: '{_length}', written '{_offset}'.");
throw new InvalidOperationException($"Entire reserved length was not used. Length: '{_capacity}', written '{_offset}'.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

length -> capacity?

Copy link

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

Remember to create the TODO task.

@pakrym pakrym merged commit 449f64d into dev Sep 30, 2016
namespace Microsoft.Extensions.Primitives
{
[DebuggerDisplay("Value = {_value}")]
public struct InplaceStringBuilder

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a lil late, but we should add a comment that this should only be used for well-known reasonably sized strings. For everything else, use StringBuilder. (Primarily because user code would see this via HttpAbstractions \ Mvc)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add something scary but true? "otherwise it will cause a stackoverflow" maybe also "do not use across await points" though not sure it will let you anyway.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benaadams why would it cause stackoverflow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry thought it was stackalloc'd, reading too many PRs. This wouldn't cause a stack overflow; though it might upset some people on the clr team ;-)

var formatter = new InplaceStringBuilder(5);
formatter.Append("123");
var exception = Assert.Throws<InvalidOperationException>(() => formatter.Build());
Assert.Equal(exception.Message, "Entire reserved lenght was not used. Length: '5', written '3'.");
Copy link
Member

@davidfowl davidfowl Oct 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo "length"

formatter.Append("123");

var exception = Assert.Throws<InvalidOperationException>(() => formatter.IncrementLength(1));
Assert.Equal(exception.Message, "Cannot append lenght after write started.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

@JunTaoLuo JunTaoLuo deleted the pakrym/isp branch April 12, 2017 20:36
natemcmaster pushed a commit that referenced this pull request Nov 16, 2018
…master

[automated] Merge branch 'release/2.2' => 'master'
@ghost ghost locked as resolved and limited conversation to collaborators May 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants