>The timing problem might indeed be resolution dependent: 100us is probably to
>short sometimes.
Time microsecondClockValue gives the time in microseconds, but it does not
guarantee microsecond resolution, on windows the resolution is still in
milliseconds.
----------
| col |
col := Array new: 30000 streamContents: [ :stream |
1 to: 30000 do: [ :x | stream nextPut: Time microsecondClockValue ]
].
col asSet "a Set(3658909536504622 3658909536503622 3658909536502622)"'
---------
Best regards,
Henrik
-----Original Message-----
From: Pharo-dev [mailto:[email protected]] On Behalf Of Sven
Van Caekenberghe
Sent: Sunday, December 11, 2016 11:56 AM
To: Pharo Development List <[email protected]>
Subject: Re: [Pharo-dev] NeoUUIDGenerator>>testTwoSameGenerator - intermittent
CI failure
Hi Ben,
Thanks for looking into this, it was bothering me for quite some time ;-)
https://pharo.fogbugz.com/f/cases/19453/NeoUUIDGenerator-testTwoSameGenerator-intermittent-CI-failure
Yes, I think the counter roll-over is the problem, stupid of me to to have seen
this.
The timing problem might indeed be resolution dependent: 100us is probably to
short sometimes.
I will provide a slice with fixes.
Thanks again !
Regards,
Sven
> On 11 Dec 2016, at 09:07, Ben Coman <[email protected]> wrote:
>
> For Case [1] I got an unrelated CI failure [2] for
> NeoUUIDGeneratorTests>>#testTwoSameGenerator
>
> Checking this locally by running this a dozen times...
> 1 to: 1000 do: [:n| last:=n. NeoUUIDGeneratorTests new setUp
> testTwoSameGenerator ]
>
> Two distinct failures are apparent...
>
> 1. Takes longer than expected.
> self assert: (time2 - time1) abs < 100
> last=1 ==> a time difference of 109
> last=1 ==> a time difference of 102
> last=1 ==> a time difference of 155
> last=1 ==> a time difference of 105
> Interesting that whenever this happens its on the first iteration.
>
> 2. Invalid consecutive ids.
> self assert: (uuid1 at: 10) + 1 equals: (uuid2 at: 10).
> last=127 ==> TestFailure: Got 256 instead of 0.
> last=828 ==> TestFailure: Got 256 instead of 0.
> last=128 ==> TestFailure: Got 256 instead of 0.
> last=316 ==> TestFailure: Got 256 instead of 0.
> Maybe a problem with rollover?
>
> So instrumenting a bit:
> testTwoSameGenerator: n
> | uuid1 uuid2 consecutiveOk time1 time2 timeOk |
> ....
> "same generator, consequetive counters"
> consecutiveOk := ((uuid1 at: 10) + 1) = (uuid2 at: 10).
> "same generators, similar clock, within 100 milliseconds"
> time1 := self timeFromUUID: uuid1.
> time2 := self timeFromUUID: uuid2.
> timeOk := (time2 - time1) abs < 100.
> ( timeOk and: [ consecutiveOk ]) ifFalse: [
> Transcript cr;
> show: 'fail n=', (n printPaddedWith: $0 to: 3) ; tab;
> show: ' time ', ((time2 - time1) printString) , '<100'; tab;
> show: ' uuid ', (((uuid1 at: 10) + 1) printString, '=', (uuid2 at:
> 10) printString).
> ].
> self assert: consecutiveOk.
> self assert: timeOk.
>
> From playground running...
> 1 to: 1000 do: [:n|
> NeoUUIDGeneratorTests new setUp testTwoSameGenerator: n].
> Transcript crShow: 'x'.
>
> Note the 'x' was not output due to one of the consecutiveOk or timeOk asserts
> triggered each run.
> fail n=001 time 104<100 uuid 160=160
> fail n=269 time 2<100 uuid 256=0
> fail n=001 time 152<100 uuid 166=166
> fail n=117 time 3<100 uuid 256=0
> fail n=001 time 123<100 uuid 128=128
> fail n=278 time 3<100 uuid 256=0
> fail n=001 time 145<100 uuid 230=230
> fail n=673 time 1340<100 uuid 141=141
> fail n=707 time 3<100 uuid 256=0
> fail n=001 time 132<100 uuid 73=73
> fail n=001 time 117<100 uuid 206=206
> fail n=063 time 2<100 uuid 256=0
> fail n=345 time 3<100 uuid 256=0
>
> Now a strange thing is that after commenting out those two asserts for
> consecutiveOk and timeOk, the fails at n=001 stop happening.
>
> fail n=001 time 141<100 uuid 232=232
> x
> x
> fail n=201 time 3<100 uuid 256=0
> fail n=268 time 3<100 uuid 256=0
> fail n=359 time 3<100 uuid 256=0
> fail n=408 time 2<100 uuid 256=0
> fail n=559 time 3<100 uuid 256=0
> x
> fail n=139 time 3<100 uuid 256=0
> fail n=854 time 7<100 uuid 256=0
> x
> fail n=389 time 3<100 uuid 256=0
> fail n=669 time 3<100 uuid 256=0
> fail n=876 time 3<100 uuid 256=0
> fail n=916 time 3<100 uuid 256=0
> fail n=953 time 2<100 uuid 256=0
> fail n=954 time 3<100 uuid 256=0
> x
> fail n=148 time 3<100 uuid 256=0
> fail n=741 time 3<100 uuid 256=0
> x
> fail n=116 time 2<100 uuid 256=0
> fail n=480 time 3<100 uuid 256=0
> x
>
> After treating the rollover like this...
> consecutiveOk := ((uuid1 at: 10) + 1) \\ 256 = (uuid2 at: 10).
> running the last playground script gives...
>
> (Note the n=001 fail reoccurs after waiting a while between running the
> playground script again.)
> fail n=001 time 123<100 uuid 110=110
> x
> fail n=345 time 1287<100 uuid 24=24
> fail n=404 time 1313<100 uuid 125=125
> x
> x
> x
> x
> x
> fail n=449 time 1290<100 uuid 24=24
> x
> x
> x
> x
> x
>
>
> Thats looking better, so upping to 10000 iterations...
> fail n=0001 time 151<100 uuid 160=160
> fail n=2977 time 1437<100 uuid 221=221
> fail n=5498 time 1454<100 uuid 224=224
> fail n=9007 time 1351<100 uuid 239=239
> x
> fail n=3389 time 1381<100 uuid 223=223
> fail n=7768 time 1365<100 uuid 82=82
> fail n=9773 time 1395<100 uuid 164=164
> x
> fail n=3325 time 1448<100 uuid 67=67
> fail n=9930 time 1456<100 uuid 103=103
> x
> fail n=0060 time 2914<100 uuid 159=159
> fail n=1829 time 1438<100 uuid 32=32
> fail n=7918 time 1436<100 uuid 182=182
> x
>
> So the rollover looks cured.
>
> Now adding some more instrumentation to view GC Time and Time To Run
> and (see attached ST file)
>
> 0:00:00:00 TTR 0:00:00:00.001 TTR 0:00:00:00 TTR 0:00:00:00 TTR
> 0:00:00:00 TTR 0:00:00:00 TTR 0:00:00:00 TTR 0:00:00:00 TTR 0:00:00:00
> TTR 0:00:00:00
> x
> fail n=0001 time 115<100 uuid 157=157 GCTime 0 TTR 0:00:00:00
> fail n=0001 time 2<100 uuid 255=0 GCTime 0 TTR 0:00:00:00
> x
> fail n=0001 time 111<100 uuid 104=104 GCTime 0 TTR 0
> x
> fail n=0001 time 120<100 uuid 204=204 GCTime 0 TTR 0
> fail n=0001 time 1182<100 uuid 103=103 GCTime 1 TTR 1
> x
> x
> x
> x
> x
> fail n=0001 time 3<100 uuid 255=0 GCTime 0 TTR 0
> x
> x
> fail n=0001 time 1251<100 uuid 253=253 GCTime 2 TTR 1
> x
>
>
> Now I wonder at the class comment saying...
> "the first 8 bytes are the *millisecond* clock value"
> but #clockOn: is using *microsecond* clock.
> Perhaps "self assert: (time2 - time1) abs < 100"
> is meant to be 100ms not 100us ??
>
> cheers -ben
>
> [1] https://pharo.fogbugz.com/f/cases/19438
> [2]
> https://ci.inria.fr/pharo/job/Pharo-6.0-Issue-Validator/19471//artifac
> t/validationReport.html
> <NeoUUIDGeneratorTests-testTwoSameGenerator.st>