-
Type: Improvement
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Execution
Currently optional SlotIds are passed as boost::optional values that wrap the SlotId. SlotId is just an 8-byte native integer, and thus fits in a single register, whereas boost::optional is larger (a bool plus the wrapped integer, likely consuming a total of 16 bytes due to alignment). Thus there is a performance cost of fewer boost::optional arguments fitting in register for method calls, more scarce CPU cache consumed, and checking whether the value is present or boost::none needing to make a separate memory or cache lookup.
From a performance standpoint, ideally we would not require more than 8 bytes for an optional SlotId. We would also like to avoid having to check whether a SlotId is valid in the case where the SlotId is not considered optional.
Some ideas:
- constexpr SlotId NULL_SLOT_ID = -1LL;
- fast_optional<SlotId, -1>
- Debug-only assertions to check for invalid SlotIds in non-optional ones (e.g. in a struct that, in optimized builds, only contains a native integer)
- Prefixing the names of optional SlotId variables and arguments with "opt" as a code standard
The performance impact of 16 bytes vs 8 bytes is probably not a lot at higher levels of code, but at lower levels, e.g. inside tight loops, it could be substantial.