Re:Timing the time it takes to parse time
by avian on Thursday October 13, 2016 @08:23AM
(#12700222)
This is quite clever. The catch is that it assumes implementation specific details (like a little-endian architecture) while OP's code is (probably) portable C.
Re:Timing the time it takes to parse time
by dimman on Thursday October 13, 2016 @08:41AM
(#12700312)
Which part are you referring to? Bit operations etc isn't affected by endianess. It looks like it would only potentially be a problem if input is coming from another system (haven't looked at where input comes from or what format/type).
Re:Timing the time it takes to parse time
by avian on Thursday October 13, 2016 @09:16AM
(#12700520)
I was referring to this part:
Y = *(uint32_t*)s - 0x30303030;
By casting a string to a uint32_t, you are assuming the memory layout of uint32_t. Y will have a different value depending on architecture. E.g. on a typical little-endian you will get 0x06010002. On big-endian you will get 0x02000106.I'm talking about C, however. I didn't notice the post is talking about C#. Things might be better defined there.
Re:Timing the time it takes to parse time
by JoeAltmaier on Thursday October 13, 2016 @09:27AM
(#12700585)
Regardless of layout, that subtraction will have the same effect on most printable characters. An identical effect on digits.
Re:Timing the time it takes to parse time
by avian on Thursday October 13, 2016 @09:38AM
(#12700660)
The cast is the problematic part, not the subtraction.
Re:Timing the time it takes to parse time
by JoeAltmaier on Thursday October 13, 2016 @09:53AM
(#12700749)
If there is no carry, then I don't understand. Four bytes will have the same value deducted. regardless of the byte order. If there is no carry implication (all are digits) then there is no issue.
Re:Timing the time it takes to parse time
by huhtenberg on Thursday October 13, 2016 @09:58AM
(#12700780)
On RISC platforms
*(uint32_t*)s
will get you a SIGBUS if s is not aligned to a 4-byte boundary. Though that's another issue, not what OP was referring to.
Re:Timing the time it takes to parse time
by zeusk on Thursday October 13, 2016 @02:40PM
(#12703014)
ARM has unaligned access since v6 (introduced in 2001); if you're on linux, unaligned access will be patched by the kernel (as was the case prior ARMv6 and even for MIPS afaik).
Anyway, the point of his post was about possible gains from removing validation, not about being portable or production code.
Re:Timing the time it takes to parse time
by larvyde on Thursday October 13, 2016 @07:56PM
(#12705195)
The subtraction isn't the issue, the cast is. the string "2016" is represented by the byte sequence [0x32, 0x30, 0x31, 0x36]. Casting this array to a uint32* in big endian gives you the integer 0x32303136 (or 842019126) while in little endian gives you the integer 0x36313032 (or 909193266).
Re:Timing the time it takes to parse time
by JoeAltmaier on Thursday October 13, 2016 @11:46PM
(#12706009)
...and subtracting 0x30303030 works to exactly the same effect on either one!
Re:Timing the time it takes to parse time
by larvyde on Saturday October 15, 2016 @04:47AM
(#12713281)
0x32303136 - 0x30303030 = 0x02000106
0x36313032 - 0x30303030 = 0x06010002
how is 0x02000106 the same as 0x06010002?
Re:Timing the time it takes to parse time
by JoeAltmaier on Tuesday October 18, 2016 @10:35AM
(#12734756)
When you show the string in memory order, they are the same. Its the operation on the string that's important, not the way you print the hex byte-order-dependent value. Both become 01 00 01 06
Re:Timing the time it takes to parse time
by larvyde on Wednesday October 19, 2016 @12:48AM
(#12741148)
But we're trying to convert the string "2016" to the integer 2016.
we want to turn the sequence [0x32, 0x30, 0x31, 0x36] (same on both architectures) into [0x00, 0x00, 0x07, 0xe0] in big endian or [0xe0, 0x07, 0x00, 0x00] in little endian. You can't simply perform the same procedure in both architectures since it'll result in a reversed sequence in one of them...
Y>>24 will be the byte at +3 on a little-endian system, or +0 on a big-endian system. It's therefore the digit in the 10^0 column in the former case, or the 10^3 column in the latter.
So it actually looks like it currently assumes a big-endian system.
I wonder what the speedup will be from omitting all the validation and associated branching and just picking the values out directly. Chances are that you won't see more than one date format in the same input either. Another strategy I'd use is to parallelise the digitisation; assuming the YYYY-MM-DDTHH:mm:ss format, it'd start off something like this (untested, but should be close if not completely correct):
It should be possible to reduce the year computation to 2 multiplications, at the expense of several more masking operations. Around 50-100 clock cycles per full datetime should be possible, which is in the few-dozen-ns range on a GHz-clock CPU. Probably could go a bit faster still if you start bringing in the SSE...