I have to ask: does anyone recall the benchmarks that showed that bounds checks or vector reallocations were a measurable performance hit in this code?
If we don't, we should just write simple, obviously correct code. If we do, there should be a comment to that effect, or something to convey to readers the performance constraints this code is trying to satisfy. On Tue, Aug 1, 2017 at 2:10 PM, Kris Maglione <kmagli...@mozilla.com> wrote: > On Tue, Aug 01, 2017 at 01:28:37PM -0700, Eric Rahm wrote: > >> Both AppendElements and SetLength default initialize the values, there's >> no >> intermediate uninitialzed state. SetCapacity doesn't initialize the >> values, >> but they're also not indexable -- we have release bounds assertions -- >> unless you try really hard. >> > > For a lot of cases, default initialized isn't much better than completely > uninitialized. And it has an additional, unnecessary performance penalty > for the pattern that you suggested. > > SetCapacity brings us back to the same problem where we either have > unnecessary allocation checks for every element we append, or we skip > sanity checks entirely and hope things stay sane if we refactor. > > With the infallible*() methods of the Vector class, though, we don't have > to worry about any of that, and the code you suggested below becomes > something like: > > Vector<Socket> sockets; > if (!sockets.reserve(inputs.length())) > return false; > > for (auto input : inputs) > sockets.infallibleEmplaceBack(input); > > and we still get automatic allocation sanity checks and bounds accounting, > but without any release overhead from default initialization, allocation > checks, or unnecessary reallocations. > > And since that's the natural pattern for appending a fixed number of > elements to a Vector, it doesn't really require any thought when writing > it. The safe and efficient approach is basically the default option. > > > nsTArray doesn't support emplace although it does have AppendElement(T&&), >> but that wouldn't really help in this case. It's possible we could add >> that >> of course! >> >> -e >> >> On Tue, Aug 1, 2017 at 1:11 PM, Kris Maglione <kmagli...@mozilla.com> >> wrote: >> >> On Tue, Aug 01, 2017 at 12:57:31PM -0700, Eric Rahm wrote: >>> >>> nsTArray has various Append methods, in this case just using the >>>> infallible >>>> AppendElements w/o out a SetCapacity call would do the job. Another >>>> option >>>> would be to use SetLength which would default initialize the new >>>> elements. >>>> >>>> If we're trying to make things fast-but-safeish in this case, the >>>> preferred >>>> way is probably: >>>> >>>> auto itr = AppendElements(length, fallible); >>>> if (!itr) ... >>>> >>>> // no bounds checking >>>> for (...; i++, itr++) >>>> auto& mSocket = *itr; >>>> >>>> // bounds checking >>>> for (...) >>>> auto& mSocket = *sockets[i]; >>>> >>>> In general I agree the pattern of fallibly allocating and then fallibly >>>> appending w/o checking the return value is a bit silly. Perhaps we >>>> should >>>> just mark the fallible version MUST_USE? It looks like it's commented >>>> out >>>> for some reason (probably a ton of bustage). >>>> >>>> >>> Honestly, I think the Vector infallible* methods are a much cleaner way >>> to >>> handle this, especially when we need something like >>> infallibleEmplaceBack. >>> They tend to encourage writing more efficient code, with fewer >>> reallocations and allocation checks. And I think the resulting code tends >>> to be safer than AppendElements followed by unchecked raw pointer access, >>> placement `new`s, and an intermediate state where we have a bunch of >>> indexable but uninitialized elements in the array. >>> >>> That's been my experience when reading and writing code using the various >>> approaches, anyway. >>> >>> >>> On Tue, Aug 1, 2017 at 12:18 PM, Kris Maglione <kmagli...@mozilla.com> >>> >>>> wrote: >>>> >>>> On Tue, Aug 01, 2017 at 12:31:24PM -0400, Alexis Beingessner wrote: >>>> >>>>> >>>>> I was recently searching through our codebase to look at all the ways >>>>> we >>>>> >>>>>> use fallible allocations, and was startled when I came across several >>>>>> lines >>>>>> that looked like this: >>>>>> >>>>>> dom::SocketElement &mSocket = *sockets.AppendElement(fallible); >>>>>> ... >>>>>> So in isolation this code is saying "I want to handle allocation >>>>>> failure" >>>>>> and then immediately not doing that and just dereferencing the result. >>>>>> This >>>>>> turns allocation failure into Undefined Behaviour, rather than a >>>>>> process >>>>>> abort. >>>>>> >>>>>> Thankfully, all the cases where I found this were preceded by >>>>>> something >>>>>> like the following: >>>>>> >>>>>> uint32_t length = socketData->mData.Length();if >>>>>> (!sockets.SetCapacity(length, fallible)) { JS_ReportOutOfMemory(cx); >>>>>> return NS_ERROR_OUT_OF_MEMORY;}for (uint32_t i = 0; i < >>>>>> socketData->mData.Length(); i++) { dom::SocketElement &mSocket = >>>>>> *sockets.AppendElement(fallible); >>>>>> >>>>>> >>>>>> >>>>>> So really, the fallible AppendElement *is* infallible, but we're just >>>>>> saying "fallible" anyway. I find this pattern concerning for two >>>>>> reasons: >>>>>> >>>>>> >>>>>> The MFBT Vector class handles this with a set of infallibleAppend[1] >>>>> methods that assert that space has been reserved for the new elements >>>>> before they're called. If we're using this pattern elsewhere without >>>>> the >>>>> same safeties, either those places should probably switch to using >>>>> Vectors, >>>>> or we should probably add similar checked infallible methods to >>>>> nsTArray. >>>>> >>>>> >>>>> [1]: http://searchfox.org/mozilla-central/rev/bbc1c59e460a27b2092 >>>>> 9b56489e2e55438de81fa/mfbt/Vector.h#707-733 >>>>> >>>>> _______________________________________________ >>>>> dev-platform mailing list >>>>> dev-platform@lists.mozilla.org >>>>> https://lists.mozilla.org/listinfo/dev-platform >>>>> >>>>> >>>>> -- >>> Kris Maglione >>> Senior Firefox Add-ons Engineer >>> Mozilla Corporation >>> >>> Science is interesting, and if you don't agree you can fuck off. >>> --Nigel Calder, former editor of New Scientist >>> >>> >>> > -- > Kris Maglione > Senior Firefox Add-ons Engineer > Mozilla Corporation > > I'm confident that tomorrow's Unix will look like today's Unix, only > cruftier. > --Russ Cox > > > _______________________________________________ > dev-platform mailing list > dev-platform@lists.mozilla.org > https://lists.mozilla.org/listinfo/dev-platform > _______________________________________________ dev-platform mailing list dev-platform@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-platform