Skip to content
This repository has been archived by the owner on Nov 20, 2018. It is now read-only.

Extend WebEncoders API to avoid allocations within the methods #563

Closed
wants to merge 3 commits into from

Conversation

dougbu
Copy link
Member

@dougbu dougbu commented Feb 16, 2016

  • rewrite existing methods in terms of the new ones
  • don't allocate multiple 0-length arrays

nit:

  • clarify a couple of doc comments e.g. using <paramref/>
  • move an error message into a resource
    • pass parameter names into new resource
  • rename parameters for consistency e.g. inputLength -> count

@dougbu
Copy link
Member Author

dougbu commented Feb 16, 2016

/cc @Tratcher @rynowak

dougbu added a commit to aspnet/Antiforgery that referenced this pull request Feb 16, 2016
- #23 part 4
- depends on aspnet/HttpAbstractions#563

nits:
- correct name of a field in `AntiforgerySerializationContext`
- avoid allocations when returning an `AntiforgerySerializationContext` in (unlikely) case `Stream` is unused
// If the caller provided invalid base64 chars, they'll be caught here.
return Convert.FromBase64CharArray(completeBase64Array, 0, completeBase64Array.Length);
return Convert.FromBase64CharArray(input, offset, arraySizeRequired);
Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this call allocates. Convert doesn't offer a way around it.

@Tratcher
Copy link
Member

Why are you making this change?

@dougbu
Copy link
Member Author

dougbu commented Feb 16, 2016

Why are you making this change?

Because the allocations done inside WebEncoders are significant for the Antiforgery use of this code. See numbers in aspnet/Antiforgery#56.

@davidfowl
Copy link
Member

Seems like it might be worthwhile to consider a low allocation pattern where the user provides all of the input and output structures. They way they can pool arrays or instead of us having to new things up. The only issue might be knowing what the size of the output array is. I wonder of there are any nice patterns for doing this.

- rewrite existing methods in terms of the new ones
- don't allocate multiple 0-length arrays

nit:
- clarify a couple of doc comments e.g. using `<paramref/>`
- move an error message into a resource
 - pass parameter names into new resource
- rename parameters for consistency e.g. `inputLength` -> `count`
dougbu added a commit to aspnet/Antiforgery that referenced this pull request Feb 17, 2016
- #23 part 4
- depends on aspnet/HttpAbstractions#563

nits:
- correct name of a field in `AntiforgerySerializationContext`
- avoid allocations when returning an `AntiforgerySerializationContext` in (unlikely) case `Stream` is unused
dougbu added a commit to aspnet/Antiforgery that referenced this pull request Feb 17, 2016
Also name literal `int` parameters.
@dougbu
Copy link
Member Author

dougbu commented Feb 17, 2016

🆙📅

/// <returns>
/// The number of characters written to <paramref name="output"/>, less any padding characters.
/// </returns>
public static int Base64UrlEncode(byte[] input, int offset, int count, char[] output, int outputOffset)
Copy link
Member

Choose a reason for hiding this comment

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

By convention, the count in these methods always comes last (Buffer.BlockCopy, string.Compare)

Copy link
Member Author

Choose a reason for hiding this comment

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

Not always and I followed what Convert.ToBase64CharArray() exposes. See https://github.com/aspnet/HttpAbstractions/pull/563/files#diff-3fdfb7eef02148bf1131ee1c77af1fe6R282 But I don't feel strongly. Do you?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thought about this a bit more, Convert.ToBase64CharArray() is the odd one out. I'll move count to the end here and in the new Base64UrlDecode() overload.

@rynowak
Copy link
Member

rynowak commented Feb 18, 2016

:shipit: from me with some minor comments - this will meet our needs.

Another option here is to use stackalloc with the intermediate array, but that has its own gotchas.

- more `var`
- move `count` parameters to the end

Also added a test covering the new overloads.
@dougbu
Copy link
Member Author

dougbu commented Feb 18, 2016

8c120a0

@dougbu dougbu closed this Feb 18, 2016
@dougbu
Copy link
Member Author

dougbu commented Feb 18, 2016

BTW @rynowak

Another option here is to use stackalloc with the intermediate array

This option is now open for callers. For example, if the DataProtections use of WebEncoders in public static string Protect(this IDataProtector protector, string plaintext) or public static string Unprotect(this IDataProtector protector, string protectedData) show up in tested scenarios, we could use stackalloc there.

@dougbu dougbu deleted the dougbu/expose.arrays branch February 18, 2016 07:28
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

5 participants