Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Making int.Parse("") faster#12196

Closed
alexandrnikitin wants to merge 1 commit intodotnet:masterfrom
alexandrnikitin:spike-faster-int-parse
Closed

Making int.Parse("") faster#12196
alexandrnikitin wants to merge 1 commit intodotnet:masterfrom
alexandrnikitin:spike-faster-int-parse

Conversation

@alexandrnikitin
Copy link

This is a PoC to to make int.Parse() faster for 99%? cases.
The fast path only handles the NumberStyles.Integer style (sign, leading and trailing whitespaces)
This is a draft version. I will polish it if there's interest to have it in CLR. It reuses two functions MatchChars and IsWhite. I believe it's possible to make it faster (some magic with the loop and conditions, get rid of unsafe code and MatchChars function). It also possible to improve all cases where NumberStyles.Integer used
I pushed initial benchmarks to a separate repo (I didn't manage to do them in the coreclr repos 😕 )

Benchmark results:

Method Mean Error StdDev
OneDigit 60.28 ns 1.5539 ns 0.4036 ns
MaxValue 105.17 ns 3.4847 ns 0.9051 ns
Sign 109.57 ns 4.4545 ns 1.1570 ns
Whitespaces 136.43 ns 4.3078 ns 1.1189 ns
FasterOneDigit 18.97 ns 0.6642 ns 0.1725 ns
FasterMaxValue 30.68 ns 2.4894 ns 0.6466 ns
FasterSign 41.97 ns 0.9735 ns 0.2529 ns
FasterWhitespaces 208.79 ns 6.2361 ns 1.6198 ns

Not sure what's wrong with the Whitespaces case 😊

Related issues: #3995 https://github.com/dotnet/corefx/issues/13293 #3163
cc who participated in previous discussions @jkotas @varocarbas @hughbe @danmosemsft @jakobbotsch @mikedn

@jkotas
Copy link
Member

jkotas commented Jun 9, 2017

cc @KrzysztofCwalina

@mikedn
Copy link

mikedn commented Jun 9, 2017

Have you tried using separate loops instead of a single loop and "state"?

@alexandrnikitin
Copy link
Author

@mikedn Yeah, there's definitely room for optimizations!! I just wanted to initiate a discussion. If it's worth to do it (it's not only int related), I'll make it as fast as I can :)

@varocarbas
Copy link

Note that I did some quick experiments on these lines some months ago and my conclusion was that this alternative wasn't worth pursuing (didn't try it too hard though). I think that I mostly focused on long, but these conclusions should hold here too: very slight improvements only by analysing the long cases (+ irregular behaviours better/worse depending upon the specific sub-scenario); and even what seemed slightly slower performances in other cases, provoked by the inclusion of more functions in mscorlib (note that I intended to somehow emulate the existing structure, formed by various methods calling one to the other).

I am also in a position to say that further improving the main existing algorithm would be quite difficult, as far as it is already over-optimised (even though, some parts might look like easily optimisable at first sight).

I am not trying to demotivate you, but to give some context about the kind of difficulties which you are about to face. As a first step (I learned that the hard way, mostly thanks to @jkotas contributions :)), you should set up a reliable enough testing framework (in principle, many iterations and quite simplistic actions) to get a proper feeling about what you really have (is your table referring to fractions of nanosecond improvements?!).

@Pzixel
Copy link

Pzixel commented Jun 9, 2017

It could be much better if System.Numerics.Vector was referenced by corlib by default. Such things are very profitable from SIMD operations (we could make up to 8 digits per clock), however afaik we are unable to use Vector class in such basic classes.

I also have a question about unsafe: why? Bound checks are elminitated anyway because you are passing whole string, but you even may make it slower by pinning a string. DId you try benchmark very same algorithm without unsafe?

@jamesqo
Copy link

jamesqo commented Jun 19, 2017

@Pzixel There is an issue for being able to use Vector in corelib: https://github.com/dotnet/coreclr/issues/8104. Unfortunately, it would require significant infrastructure changes so there needs to be perf measurements to determine it's worth it.

@Pzixel
Copy link

Pzixel commented Jun 19, 2017

@jamesqo AFAIR Sasha Goldshtein @goldshtn showed that SIMD instricts can speedup operations such as string comparasion and GetHashCode in 4-8 times. It's quite good and doesn't require any specific hacks.

@dotnet dotnet deleted a comment from varocarbas Jun 19, 2017
@karelz
Copy link
Member

karelz commented Jun 19, 2017

@varocarbas your comment was deleted as a violation of the ,NET Foundation Code of Conduct (adopted by CoreCLR repo) as it was insulting/derogatory. You may consider this an official warning.

@dotnet dotnet deleted a comment from varocarbas Jun 19, 2017
@karelz
Copy link
Member

karelz commented Jun 19, 2017

@varocarbas your comment was deleted as a violation of the .NET Foundation Code of Conduct (adopted by CoreCLR repo) as it was insulting/derogatory. You may consider this an official warning.

@karelz
Copy link
Member

karelz commented Jun 19, 2017

@varocarbas we'll be happy to share with you your original comments offline and explain in more details which parts of your comments are insulting/derogatory. Please reach out to us via email at .NET Foundation Code of Conduct (conduct@dotnetfoundation.org).

In case of Code of Conduct violations, we delete entire post. No exceptions. We want to create safe and creative environment for our community, where people are respectful to each other.

@varocarbas please do not continue discussing this issue here. Please reach out to us offline, so that we can discuss acceptable behavior according to our Code of Conduct.

@Pzixel
Copy link

Pzixel commented Jun 20, 2017

@varocarbas I have to admit that I really got hurted by your post. But after rereading it several times I found that it prolably have neutral intention. So, I have no beefing toward you, but someone may be less tolerant.

About your position above, I have studied this code snippet more carefuly and I have found that the reason why it cannot be converted is MatchChars, which have no idea about bounds and will defenitly insert bound checks everywhere if we write it using regular loops. Without it, it's just an iteration through a whole string which is ok with these loops. But, we have some functions that don't provide such information, and may be optimized using unsafe. You just could point me to that fact directly, instead of rtfm. Anyway, we decided that author is completely right here so I propose to end this discussion branch here.

Finally, I'm not saying that everythigh is good with vectorisation. But some very common patterns may heavily profit from it. Operation with strings is 90% of time in some cases. I understand, that there is plenty of problems that need solution and it may be not first-priority task, but I propose to assume it at least as worthwhile task.

{
state |= StateSign;
ret = ret * 10 + (c - '0');
}
Copy link
Member

Choose a reason for hiding this comment

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

Another possible optimization here:

var c = *cptr;
uint cbased = (uint)(c - '0');
if (cbased <= 9 && (state & StateDigits) == 0)
{
  state |= StateSign;
  ret = ret * 10 + (int)cbased;
}

Copy link
Author

Choose a reason for hiding this comment

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

applied, thanks. The asm code looks better but it doesn't give much in a benchmark.

}


if ((state & StateNegative) > 0)
Copy link
Member

@jakobbotsch jakobbotsch Jun 20, 2017

Choose a reason for hiding this comment

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

This check relies on StateNegative not being the sign bit. Would probably be more appropriate to just use != 0 (at least this is how I usually see flag checks).

Copy link
Author

Choose a reason for hiding this comment

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

agreed, thanks

@alexandrnikitin
Copy link
Author

Have you tried using separate loops instead of a single loop and "state"?

@mikedn I pushed the three loop version and its benchmark results to the repo.

@Pzixel
Copy link

Pzixel commented Jun 20, 2017

@varocarbas don't worry, I have all your posts persistet on my email because I have a notification on. I can resend it for you somehow, If you want so.

About your post: I know what is unsafe for, but I know lots of people abusing it without knowing all pros and cons. Easy test: you can write a simple for-loop that is summing charcodes and do same thing via unsafe. And there is guys who think that second approach is always faster, which is not true of course. I didn't talk about hey, let's replace pointer arithmetics with substring, it's kinda same thing, becuase it's obviosly wrong. I was talking about completely different thing and I the point I missed and which is making unsafe approach viable.

@mikedn
Copy link

mikedn commented Jun 20, 2017

I pushed the three loop version and its benchmark results to the repo.

Looks like it's slower. Most likely due to the cost of IsWhite and MatchChars which are now always executed, previously they were not executed if the first character was a digit.

This MatchChars thing is rather unfortunate as it looks like all .NET cultures use + and - for PositiveSign and NegativeSign. We should optimize for the common case(s):

  • most numbers start with a digit (no whitespace, no sign) - your initial code did this
  • most numbers start with a digit or - (no whitespace, no +, no culture specific signs) - this might be the ideal approach as it includes negative numbers (unlike the previous case)

if ((state & StateNegative) > 0)
{
ret = -ret;
if (ret > 0)
Copy link

Choose a reason for hiding this comment

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

I don't think these 2 checks are enough to detect overflow. They're enough only if we limit the number of digits you parse and I don't see such a limit in your code.

Copy link
Author

Choose a reason for hiding this comment

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

addressed using ret >= 0 check

                handleNumber:
                var c = (uint)(*cptr - '0');
                if (c <= 9 && ret >= 0)
                {
                    ret = ret * 10 + (int)c;
                    cptr++;
                    goto handleNumber;
                }

@alexandrnikitin alexandrnikitin force-pushed the spike-faster-int-parse branch from dab26ea to 0b79cc8 Compare August 8, 2017 08:07
@alexandrnikitin
Copy link
Author

I rebased and pushed a new version that addresses comments. I extracted code that handles leading and trailing whitespaces into separate NoInlining methods.
One more possible optimization is to wrap OverflowException and ArgumentNullException into separate NoInlining methods. This will reduce JITed code size from 419 to 258 bytes. I'm not sure it's worth it though.

Benchmark results:

Method Mean Error StdDev
OneDigit 61.22 ns 0.4538 ns 0.4245 ns
FiveDigits 81.14 ns 0.2538 ns 0.1982 ns
MaxValue 110.98 ns 0.7392 ns 0.6915 ns
Whitespaces 139.47 ns 1.5151 ns 1.4173 ns
NegativeOneDigit 65.97 ns 0.7266 ns 0.6441 ns
NegativeFiveDigits 89.70 ns 0.4455 ns 0.3478 ns
NegativeMaxValue 119.81 ns 1.2015 ns 1.0651 ns
OneDigitImproved 22.39 ns 0.3000 ns 0.2806 ns
FiveDigitsImproved 26.40 ns 0.3222 ns 0.2516 ns
MaxValueImproved 34.26 ns 0.2432 ns 0.1899 ns
WhitespacesImproved 69.03 ns 0.8523 ns 0.7972 ns
NegativeOneDigitImproved 27.56 ns 0.1895 ns 0.1680 ns
NegativeFiveDigitsImproved 31.61 ns 0.2668 ns 0.2365 ns
NegativeMaxValueImproved 64.05 ns 1.3138 ns 2.2310 ns

The assembly code for RyuJitX64 : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2101.1

0:000> !U /d 00007ff838540900
Normal JIT generated code
MakingIntParseFaster.V5.FasterInt.ParseInt32Fast(System.String, System.Globalization.NumberFormatInfo)
Begin 00007ff838540900, size 1a3

; if (s == null) throw new ArgumentNullException(nameof(s));
>>> 00007ff8`38540900 4156            push    r14
00007ff8`38540902 57              push    rdi
00007ff8`38540903 56              push    rsi
00007ff8`38540904 55              push    rbp
00007ff8`38540905 53              push    rbx
00007ff8`38540906 4883ec30        sub     rsp,30h
00007ff8`3854090a 33c0            xor     eax,eax
00007ff8`3854090c 4889442428      mov     qword ptr [rsp+28h],rax
00007ff8`38540911 4889442420      mov     qword ptr [rsp+20h],rax
00007ff8`38540916 488bf2          mov     rsi,rdx
00007ff8`38540919 4885c9          test    rcx,rcx
00007ff8`3854091c 0f840e010000    je      00007ff8`38540a30

; var isNegative = false;
00007ff8`38540922 33ff            xor     edi,edi

; var ret = 0;
00007ff8`38540924 33db            xor     ebx,ebx
00007ff8`38540926 48894c2428      mov     qword ptr [rsp+28h],rcx

; fixed (char* sptr = s)
00007ff8`3854092b 488be9          mov     rbp,rcx
00007ff8`3854092e 4885ed          test    rbp,rbp
00007ff8`38540931 7404            je      00007ff8`38540937
00007ff8`38540933 4883c50c        add     rbp,0Ch

; var cptr = sptr;
00007ff8`38540937 48896c2420      mov     qword ptr [rsp+20h],rbp

; var eptr = sptr + s.Length;
00007ff8`3854093c 8b5108          mov     edx,dword ptr [rcx+8]
00007ff8`3854093f 4863d2          movsxd  rdx,edx
00007ff8`38540942 4c8d745500      lea     r14,[rbp+rdx*2]

; var c = (uint)(*cptr - '0');
00007ff8`38540947 488b542420      mov     rdx,qword ptr [rsp+20h]
00007ff8`3854094c 0fb712          movzx   edx,word ptr [rdx]
00007ff8`3854094f 83c2d0          add     edx,0FFFFFFD0h

; if (c <= 9 && ret >= 0)
00007ff8`38540952 83fa09          cmp     edx,9
00007ff8`38540955 771a            ja      00007ff8`38540971
00007ff8`38540957 85db            test    ebx,ebx
00007ff8`38540959 7c16            jl      00007ff8`38540971

; ret = ret * 10 + (int)c;
00007ff8`3854095b 8d0c9b          lea     ecx,[rbx+rbx*4]
00007ff8`3854095e 8d1c4a          lea     ebx,[rdx+rcx*2]

; cptr++;
00007ff8`38540961 488b542420      mov     rdx,qword ptr [rsp+20h]
00007ff8`38540966 4883c202        add     rdx,2
00007ff8`3854096a 4889542420      mov     qword ptr [rsp+20h],rdx
00007ff8`3854096f ebd6            jmp     00007ff8`38540947

; if (cptr == eptr)
00007ff8`38540971 488b542420      mov     rdx,qword ptr [rsp+20h]
00007ff8`38540976 493bd6          cmp     rdx,r14
00007ff8`38540979 7456            je      00007ff8`385409d1

; else if (cptr == sptr)
00007ff8`3854097b 488b542420      mov     rdx,qword ptr [rsp+20h]
00007ff8`38540980 483bd5          cmp     rdx,rbp
00007ff8`38540983 7535            jne     00007ff8`385409ba

; var next = MatchChars(cptr, info.NegativeSign);
00007ff8`38540985 488b4c2420      mov     rcx,qword ptr [rsp+20h]
00007ff8`3854098a 488b5628        mov     rdx,qword ptr [rsi+28h]
00007ff8`3854098e e83df7ffff      call    00007ff8`385400d0 (MakingIntParseFaster.V5.FasterInt.MatchChars(Char*, System.String), mdToken: 0000000006000048)

; if (next != null)
00007ff8`38540993 4885c0          test    rax,rax
00007ff8`38540996 740c            je      00007ff8`385409a4

; isNegative = true;
00007ff8`38540998 bf01000000      mov     edi,1

; cptr = next;
00007ff8`3854099d 4889442420      mov     qword ptr [rsp+20h],rax
00007ff8`385409a2 eba3            jmp     00007ff8`38540947

; isNegative = HandleLeadingSymbols(ref cptr, eptr, info);
00007ff8`385409a4 488d4c2420      lea     rcx,[rsp+20h]
00007ff8`385409a9 498bd6          mov     rdx,r14
00007ff8`385409ac 4c8bc6          mov     r8,rsi
00007ff8`385409af e8fcf6ffff      call    00007ff8`385400b0 (MakingIntParseFaster.V5.FasterInt.HandleLeadingSymbols(Char* ByRef, Char*, System.Globalization.NumberFormatInfo), mdToken: 0000000006000044)
00007ff8`385409b4 400fb6f8        movzx   edi,al
00007ff8`385409b8 eb8d            jmp     00007ff8`38540947

; else if (cptr < eptr)
00007ff8`385409ba 488b4c2420      mov     rcx,qword ptr [rsp+20h]
00007ff8`385409bf 493bce          cmp     rcx,r14
00007ff8`385409c2 730d            jae     00007ff8`385409d1

; HandleTrailingWhite(cptr, eptr);
00007ff8`385409c4 488b4c2420      mov     rcx,qword ptr [rsp+20h]
00007ff8`385409c9 498bd6          mov     rdx,r14
00007ff8`385409cc e8f7f6ffff      call    00007ff8`385400c8 (MakingIntParseFaster.V5.FasterInt.HandleTrailingWhite(Char*, Char*), mdToken: 0000000006000047)

; if (isNegative)
00007ff8`385409d1 33c0            xor     eax,eax
00007ff8`385409d3 4889442428      mov     qword ptr [rsp+28h],rax
00007ff8`385409d8 85ff            test    edi,edi
00007ff8`385409da 7417            je      00007ff8`385409f3

; ret = -ret;
00007ff8`385409dc f7db            neg     ebx

; if (ret > 0) throw new OverflowException("SR.Overflow_Int32");
00007ff8`385409de 85db            test    ebx,ebx
00007ff8`385409e0 0f8f83000000    jg      00007ff8`38540a69

; return ret;
00007ff8`385409e6 8bc3            mov     eax,ebx
00007ff8`385409e8 4883c430        add     rsp,30h
00007ff8`385409ec 5b              pop     rbx
00007ff8`385409ed 5d              pop     rbp
00007ff8`385409ee 5e              pop     rsi
00007ff8`385409ef 5f              pop     rdi
00007ff8`385409f0 415e            pop     r14
00007ff8`385409f2 c3              ret

; if (ret < 0) throw new OverflowException("SR.Overflow_Int32");
00007ff8`385409f3 85db            test    ebx,ebx
00007ff8`385409f5 7def            jge     00007ff8`385409e6
00007ff8`385409f7 48b9f0691087f87f0000 mov rcx,offset mscorlib_ni+0x7169f0 (00007ff8`871069f0) (MT: System.OverflowException)
00007ff8`38540a01 e81a1b5f5f      call    clr!JIT_TrialAllocSFastMP_InlineGetThread (00007ff8`97b32520)
00007ff8`38540a06 488bf0          mov     rsi,rax
00007ff8`38540a09 b947000000      mov     ecx,47h
00007ff8`38540a0e 48baf8404238f87f0000 mov rdx,7FF8384240F8h
00007ff8`38540a18 e80398795f      call    clr!JIT_StrCns (00007ff8`97cda220)
00007ff8`38540a1d 488bd0          mov     rdx,rax
00007ff8`38540a20 488bce          mov     rcx,rsi
00007ff8`38540a23 e84853254f      call    mscorlib_ni+0xda5d70 (00007ff8`87795d70) (System.OverflowException..ctor(System.String), mdToken: 00000000060010a9)
00007ff8`38540a28 488bce          mov     rcx,rsi
00007ff8`38540a2b e810e6735f      call    clr!IL_Throw (00007ff8`97c7f040)

; if (s == null) throw new ArgumentNullException(nameof(s));
00007ff8`38540a30 48b9783a1087f87f0000 mov rcx,offset mscorlib_ni+0x713a78 (00007ff8`87103a78) (MT: System.ArgumentNullException)
00007ff8`38540a3a e8e11a5f5f      call    clr!JIT_TrialAllocSFastMP_InlineGetThread (00007ff8`97b32520)
00007ff8`38540a3f 488bf0          mov     rsi,rax
00007ff8`38540a42 b977000000      mov     ecx,77h
00007ff8`38540a47 48baf8404238f87f0000 mov rdx,7FF8384240F8h
00007ff8`38540a51 e8ca97795f      call    clr!JIT_StrCns (00007ff8`97cda220)
00007ff8`38540a56 488bd0          mov     rdx,rax
00007ff8`38540a59 488bce          mov     rcx,rsi
00007ff8`38540a5c e8f75b8e4e      call    mscorlib_ni+0x436658 (00007ff8`86e26658) (System.ArgumentNullException..ctor(System.String), mdToken: 0000000006000977)
00007ff8`38540a61 488bce          mov     rcx,rsi
00007ff8`38540a64 e8d7e5735f      call    clr!IL_Throw (00007ff8`97c7f040)

; if (ret > 0) throw new OverflowException("SR.Overflow_Int32");
00007ff8`38540a69 48b9f0691087f87f0000 mov rcx,offset mscorlib_ni+0x7169f0 (00007ff8`871069f0) (MT: System.OverflowException)
00007ff8`38540a73 e8a81a5f5f      call    clr!JIT_TrialAllocSFastMP_InlineGetThread (00007ff8`97b32520)
00007ff8`38540a78 488bf0          mov     rsi,rax
00007ff8`38540a7b b947000000      mov     ecx,47h
00007ff8`38540a80 48baf8404238f87f0000 mov rdx,7FF8384240F8h
00007ff8`38540a8a e89197795f      call    clr!JIT_StrCns (00007ff8`97cda220)
00007ff8`38540a8f 488bd0          mov     rdx,rax
00007ff8`38540a92 488bce          mov     rcx,rsi
00007ff8`38540a95 e8d652254f      call    mscorlib_ni+0xda5d70 (00007ff8`87795d70) (System.OverflowException..ctor(System.String), mdToken: 00000000060010a9)

; if (s == null) throw new ArgumentNullException(nameof(s));
00007ff8`38540a9a 488bce          mov     rcx,rsi
00007ff8`38540a9d e89ee5735f      call    clr!IL_Throw (00007ff8`97c7f040)
00007ff8`38540aa2 cc              int     3

@karelz
Copy link
Member

karelz commented Aug 28, 2017

What is the status of the PR? No update for 3 weeks ...
Are we blocked on code reviews from MS employees? (@joperezr @AlexGhiondea)

@alexandrnikitin
Copy link
Author

@karelz Yes, it's waiting for review. Open questions:

  1. Is the perf improvement worth to introduce 3 new methods? Plus 1 more for the long type.
  2. Is it worth to wrap the exception throwing logic into helper methods? (It reduces the JITed code size significantly.)
  3. I see changes in master that use ReadOnlySpan<char> instead of string. Is that a new/ better way to work with strings?

@danmoseley
Copy link
Member

I see changes in master that use ReadOnlySpan instead of string. Is that a new/ better way to work with strings?

It's an abstraction that includes strings as well as char[] and other buffers of chars. So as you see in 12d5014 we are exposing new overloads that accept span, and implementing in terms of span (because one can have a span over string but not vice versa)

@karelz
Copy link
Member

karelz commented Sep 6, 2017

@joperezr @AlexGhiondea can you please comment? It's been 9 days :( ...

@danmoseley
Copy link
Member

danmoseley commented Sep 6, 2017

adding @stephentoub as he has been looking at improving double.Parse (https://github.com/dotnet/coreclr/issues/13544)

@stephentoub
Copy link
Member

as he has been looking at improving double.Parse

FWIW, I wasn't actually looking at improving it, only at making it work in coreclr... hadn't yet gotten around to the perf of it.

@joperezr
Copy link
Member

joperezr commented Sep 7, 2017

@alexandrnikitin thanks for your contribution, first of all I want to apologize it's taken so long for us to look into this. Before we start the review though, do you mind rebasing your changes with the changes in master since it looks like you have merge conflicts? I ask this so that I can re-run CI and to be able to run all of our corefx tests against this change to make sure that it passes them.

Handles only NumberStyles.Integer (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign)
Leading symbols handling logic wrapped into nonilineable HandleLeadingSymbols method
Trailing symbols handling logic wrapped into noninlineable HandleTrailingWhite method
@alexandrnikitin
Copy link
Author

I rebased and forcepushed the branch that works with ReadOnlySpan.

Questions I have:

  • How and where can I write tests and benchmarks for that System.Private.CoreLib build? Could you point me to the docs and examples please.
  • Is the perf improvement worth to introduce 3 new methods?
  • Is it worth to wrap the exception throwing logic into noninlineable helper methods? (It reduces the JITed code size significantly. from ~420 to 250 bytes)

@alexandrnikitin alexandrnikitin changed the title [WIP] Making int.Parse("") faster Making int.Parse("") faster Sep 8, 2017
@joperezr
Copy link
Member

@dotnet-bot test Windows_NT x86 corefx_baseline

@joperezr
Copy link
Member

How and where can I write tests and benchmarks for that System.Private.CoreLib build? Could you point me to the docs and examples please.

usually the tests are located in corefx repo which will consume these changes.

@stephentoub
Copy link
Member

@alexandrnikitin, are you still working on this / still interested in working on this?

@danmoseley
Copy link
Member

(It would be very welcome!)

@alexandrnikitin
Copy link
Author

@stephentoub I want it to be merged 😊 What options do we have from now? And what needs to be done to have it merged?

  • Resolve conflicts and keep up with all changes. I remember there was a parsing bug related to Span<>s
  • Add unit tests
  • long parsing code?
  • Wrap exception code into noninlineable methods? (not related to this, but is there a proposal for JIT that does that for all exceptions? Not the first time I see that JITted code bloats because of that)

@stephentoub
Copy link
Member

I want it to be merged

😄

What options do we have from now? And what needs to be done to have it merged?

I would say:

@jkotas
Copy link
Member

jkotas commented Jun 25, 2018

Closing stale PRs.

Ideally, this issue should be fixed by porting the fine-tuned UTF8 parser: https://github.com/dotnet/corefx/issues/30612#issuecomment-399731130

@jkotas jkotas closed this Jun 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.