Repository navigation
Reading by position is a SHOULD, with the exception an implementation's tests prove - #141
Merged
Merged
Conversation
…sition Finding Properties in both on-premise Engine specifications said every read MUST use the position. Node.js, .NET Device Detection and PHP read by name, because each measured a read by name as faster, and the fastest approach is the one used. Each specification now says every read uses the position except where the implementation's own measurement shows a read by name is faster, that the implementation records the measurement, and lists the implementations that read by name with a link to each measurement. The rest of the section is unchanged.
Contributor
Author
|
Closing and reopening at once to start the checks again, because the runs queued during GitHub's Actions outage this evening never started. |
The exception now covers a read that the implementation's own measurement shows is faster by name, rather than a whole implementation. .NET Device Detection lists only its TryGet reads as measured faster by name, and says its Value<T> and list reads also go by name though a Value<T> read measured slower by name, with the issue that moves them to the position. The Node.js and PHP items say their measurement was taken with the Device Detection Engine, and link the issues that time the IP Intelligence Engine on its own.
Both on-premise pages linked the Node.js measurement as run 42995016804, whose conclusion is failure, so a reader who opened it saw a red run and no figure. Each page now links job 130437032538 in that run, which holds the figure, in the same form the .NET item already uses. That job is itself red, so each page now says why in one sentence. The only two tests that failed in it are timing assertions, and a read by position being slower is what made them fail, which is the result the item records.
James decided that the rule is a SHOULD and that an exception stands where tests prove it. So both on-premise Engine specifications now say every read SHOULD use the position, and an implementation MAY read by name where its own tests prove a read by name is faster. The proof has to be a measurement a test or a continuous integration run takes and records, and the implementation records that run in the change that makes the read go by name. The rest of the first item is unchanged, so a typed accessor still resolves its position once, and the table of names to positions is still built once and MUST NOT be built again from a later data set. The three implementations that read by name are listed as before, each with its measurement and the issues that follow it up. The .NET entry now says plainly that its Value<T> reads, which no test proves faster by name, are outside the exception. RFC 2119 terms are upper case, as stylistic-conventions.md asks.
The list says each read by name is given with the run that proves it, but the .NET Value<T> reads are listed, go by name and have no such run, which the entry itself says four lines later. The sentence now reads "and, where there is one, the run that proves it", which holds for every entry. The same sentence is in both pages and moves together.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finding Properties in both on-premise Engine specifications said every read MUST use the position. Three implementations read by name, because each measured a read by name as faster than a read by position, and the release rule is that the fastest approach is the one used. This draft makes the rule a SHOULD, gives the exception as a MAY that an implementation's own tests have to earn, names which reads go by name in each implementation, and links each measurement and the issues that follow it up.
This draft merges into
rctogether with 51degrees-php#72, because the PHP items are true only once #72 is in. Until then PHP reads by position onrc, since 51degrees-php#66.What James decided
Asked at about 07:10 UTC on 12 November whether the exception to "Every read MUST use the position" should stand, James Rosewell said this.
So the head before that decision, 5db7141, took the wrong shape. It kept the MUST and carved an exception out of it. This head makes the rule itself a SHOULD, and makes the exception a MAY that only a measurement from a test or a continuous integration run can earn.
The problem
At d72eb07, the
rchead this branch starts from, device-detection-on-premise.md lines 202 to 209 says the following, and ip-intelligence-on-premise.md lines 408 to 415 says the same withIpRangeStartas the example.Three implementations read by name instead.
rcas f3f89811. Each getter in its SWIG wrapper is a dispatcher that tries the overload taking a name first, and given a number that attempt fails and makes a V8Error, which captures a stack trace, before the overload taking anintruns. In job 130437032538 of run 42995016804 a native read ofIsMobiletook 711 ns by name against 2,797 ns by index. The measurement was taken with the Device Detection Engine only. The read by index, its table and its tests were taken out in 927114d4.tryGetfast paths inhash_csharp.itake a name and return the value in one call, where theValue<T>getters return a value object, which costs an allocation and three more calls. In job 130391855953, on the TAC file with five names and MaxPerformance, atryGetread ofIsMobiletook 139.7 ns by name against 207.8 ns for aValue<T>read by index. AValue<T>read by name took 236.9 ns, so that kind of read is slower by name. .NET IP Intelligence reads by index.How SHOULD and MUST are written here
stylistic-conventions.md lines 72 to 77 at d72eb074 says this.
So SHOULD, MUST, MUST NOT and MAY are upper case in the new text, and the new text uses no lower case "should", "may" or "must" anywhere, as the second sentence of that convention asks. RFC 8174, which updates RFC 2119 and does not obsolete it, agrees that only the upper case forms carry the meaning.
The two terms are used in the sense RFC 2119 section 3 and section 5 give, which is that SHOULD means "there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course", and MAY means "an item is truly optional". A measurement from the implementation's own tests is the valid reason, and weighing it is reading the run.
What changes
Both files change in the same words, each naming the other Engine where it needs to.
The first item's opening sentence becomes a SHOULD, and the inline "except ..." clause the previous head carried is replaced by a plain pointer to the next item, as a SHOULD already carries its own exception and does not need one carved out of it. The rest of that item, from "A typed accessor" to "from a later data set", is word for word as it is on
rc, so the typed accessor resolving its position once, and the table built once and never built again from a later data set, stay as they are. That paragraph is wrapped again to the file's width, because the previous head left a short line in the middle of it, and no word in it changed.The second item becomes a MAY, with the proof required to be a measurement a test or a continuous integration run takes and records. A run on a developer's machine written up in prose does not count, and the implementation records the run in the change that makes the read go by name. The rest of the section is untouched.
The new text in device-detection-on-premise.md, lines 202 to 261 at 9c4822f4, is this.
ip-intelligence-on-premise.md, lines 408 to 450 at 9c4822f4, has the same two items with
IpRangeStartas the example, and lists Node.js and PHP as follows.What the previous head said
For comparison, device-detection-on-premise.md lines 202 to 216 at 5db7141b read as follows, and ip-intelligence-on-premise.md lines 408 to 422 at 5db7141b read the same.
Three things changed from those words. The rule is a SHOULD rather than a MUST with a hole in it. The exception is a MAY an implementation takes rather than a statement that a faster read "goes by name". And the proof is named, being a test or a continuous integration run that takes and records the measurement, where the previous wording accepted any "measurement".
Which reads go by name
Each item says which reads go by name, as checked in the code.
property.nameto every native getter ingetInternal(Device DetectionswigData.jslines 142 to 157 and IP Intelligence lines 105 to 155, at f76d8b05), so every read goes by name.GetValueAsBool(string propertyName), which callsTryGetBoolFast(propertyName, ...)and, only when that finds no value,getValueAsBool(propertyName)to recover the no-value message (DeviceDataHash.cslines 294 to 322 at 875acebb), and integers, doubles, strings and JavaScript in the same way. A list value goes throughGetValues(string propertyName), which calls theValue<T>gettergetValues(propertyName)(lines 378 to 390). So only theTryGetreads have a test proving them faster by name, and the item now says in those words that theValue<T>reads go by name without one, which puts them outside the exception, and that 51degrees-dotnet#139 moves them.SwigDataclasses hand each accessor the namefindPropertygives", so every read goes by name.The implementations that read by position
Each was checked in its pull requests, and every merge commit named here is in its repository's
rc.release/dotnet-parityand brought intorcby 51degrees-rust#325TryGetreads by name, listed.Value<T>reads by name with no test behind them, 51degrees-dotnet#139rcreads by position since 51degrees-php#66Checks
Both checks on the head 9c4822f passed, and the
headShaof each run was read back as that commit. The repository has nothing to build (ci/build-project.ps1prints "Nothing to build"), so these are its only checks.Every figure in the new text was read again from its job's log.
RawFastBool ns|139.7,RawNameBool ns|236.9andRawIndexBool ns|207.8. It prints no figure for a list read.History of this draft
The first head, db72e2c, listed whole implementations as reading by name and left two points open, which were whether Node.js and PHP should time IP Intelligence on their own, and whether the .NET reads with no fast path should go by position. James decided on 11 November that both go to next week, and the issues above follow them up.
The second head, 1d40cc8, makes the exception cover a read rather than a whole implementation, says only the .NET
TryGetreads are measured faster by name, and links the three issues.The third head, 5db7141, answers a review point on the second. Both pages linked the Node.js measurement as run 42995016804, whose conclusion is failure, so a reader of the published page who opened the link saw a red run and no figure. Each page now links job 130437032538 inside that run, which is where the figure is printed, in the same form the .NET item already used. That job is red as well, so each page also says in one sentence why.
The fourth head, e3097b4, is the change made to James's decision above, turning the MUST into a SHOULD and the carved-out exception into a MAY. The title of the draft changed with it, from "Read by name where an implementation measures it as faster than by position", because the draft is now about the strength of the rule as much as about the three implementations that read by name.
The fifth head, 9c4822f, is this one, and answers a review point on the fourth. The lead-in to the list promised "the change that made it and the run that proves it" for every read by name, which the .NET entry then contradicted four lines later, as the
Value<T>reads are listed and have no run behind them. The lead-in now reads "and, where there is one, the run that proves it", which holds for all three entries. The sentence is the same on both pages, so both moved together.What remains
rctogether with 51degrees-php#72, as above.src/ipi/ResultsIpi.ilines 65 to 68 at 7c4ac436).Value<T>and list reads, next week, in 51degrees-dotnet#139. Those reads now sit outside the exception in the new text, so the .NET item changes when they move.