> On 11 Dec 2016, at 12:49, Henrik Nergaard <[email protected]> wrote:
> 
>> 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)"'
> ---------

Cool test, very sad result ;-)

> 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>
> 
> 
> 


Reply via email to