Commits


Konstantin Varlamov authored and GitHub committed e241a9a9b8e
Optimize `DocumentKey` comparisons (#4123) This came up while I was investigating the effect of new C++ serializers on performance. When writing large batches, one of the hottest functions turned out to be `firebase::firestore::util::operator==(const DocumentKey& lhs, const DocumentKey& rhs)`, accounting for 15-20% of total CPU time. There are two reasons why comparing keys is currently not very efficient: * `BasePath::CompareTo`, to which this comparison eventually resolves, mistakenly uses the general-purpose `util::Compare` function rather than the more efficient `util::CompareContainer`; * the default implementation of `Comparable::operator==` results in two comparisons per element ("less-than" followed by "greater-than"), even though one would be sufficient. Fixing these issues results in 8-10% CPU time improvement when writing large batches. To work around the latter, this PR defines a new mixin `InequalityComparable` that is exactly the same as `Comparable`, except it doesn't define `operator==`, forcing the inheriting class to implement it manually. Some measurements (all done on the emulator in release mode with no logging) follow; the test case was to write 10 batches of 500 very small documents. Note that I found wall clock to fluctuate too much to be reliable and instead use the measurements from XCode's Time Profiler, which (presumably) shows CPU time. Each measurement shows total CPU time spent on `firebase::firestore::util::operator==` (all instantiations, not just for `DocumentKey`), followed by the percentage of time spent in this function compared to total runtime: * no optimization: * 275ms/18.8%; * 245ms/16.9%; * 252ms/18.5%. * `CompareContainer` optimization: * 124ms/9.7%; * 110ms/8.5%; * 128ms/10.0%. * `CompareContainer` + `ComparableWithEqual` optimizations: * 95ms/7.3%; * 100ms/8.0%; * 112ms/9.2%.