1a45d2287SDanila Kutenin================================== 2a45d2287SDanila KuteninUnspecified Behavior Randomization 3a45d2287SDanila Kutenin================================== 4a45d2287SDanila Kutenin 5a45d2287SDanila KuteninBackground 6a45d2287SDanila Kutenin========== 7a45d2287SDanila Kutenin 8a45d2287SDanila KuteninConsider the follow snippet which steadily happens in tests: 9a45d2287SDanila Kutenin 10a45d2287SDanila Kutenin 11a45d2287SDanila Kutenin.. code-block:: cpp 12a45d2287SDanila Kutenin 13a45d2287SDanila Kutenin std::vector<std::pair<int, int>> v(SomeData()); 14a45d2287SDanila Kutenin std::sort(v.begin(), v.end(), [](const auto& lhs, const auto& rhs) { 15a45d2287SDanila Kutenin return lhs.first < rhs.first; 16a45d2287SDanila Kutenin }); 17a45d2287SDanila Kutenin 18a45d2287SDanila KuteninUnder this assumption all elements in the vector whose first elements are equal 19a45d2287SDanila Kutenindo not guarantee any order. Unfortunately, this prevents libcxx introducing 20*da6a1f61SKazu Hirataother implementations because tests might silently fail and the users might 21a45d2287SDanila Kuteninheavily depend on the stability of implementations. 22a45d2287SDanila Kutenin 23a45d2287SDanila KuteninGoal 24a45d2287SDanila Kutenin=================== 25a45d2287SDanila Kutenin 26a45d2287SDanila KuteninProvide functionality for randomizing the unspecified behavior so that the users 27a45d2287SDanila Kutenincan test and migrate their components and libcxx can introduce new sorting 28a45d2287SDanila Kuteninalgorithms and optimizations to the containers. 29a45d2287SDanila Kutenin 30a45d2287SDanila KuteninFor example, as of LLVM version 13, libcxx sorting algorithm takes 31a45d2287SDanila Kutenin`O(n^2) worst case <https://llvm.org/PR20837>`_ but according 32a45d2287SDanila Kuteninto the standard its worst case should be `O(n log n)`. This effort helps users 33a45d2287SDanila Kuteninto gradually fix their tests while updating to new faster algorithms. 34a45d2287SDanila Kutenin 35a45d2287SDanila KuteninDesign 36a45d2287SDanila Kutenin====== 37a45d2287SDanila Kutenin 380a1c94f9SFangrui Song* Introduce new macro ``_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY`` which should 39a45d2287SDanila Kutenin be a part of the libcxx config. 40a45d2287SDanila Kutenin* This macro randomizes the unspecified behavior of algorithms and containers. 41a45d2287SDanila Kutenin For example, for sorting algorithm the input range is shuffled and then 42a45d2287SDanila Kutenin sorted. 43a45d2287SDanila Kutenin* This macro is off by default because users should enable it only for testing 44a45d2287SDanila Kutenin purposes and/or migrations if they happen to libcxx. 45a45d2287SDanila Kutenin* This feature is only available for C++11 and further because of 460a1c94f9SFangrui Song ``std::shuffle`` availability. 47a45d2287SDanila Kutenin* We may use `ASLR <https://en.wikipedia.org/wiki/Address_space_layout_randomization>`_ or 480a1c94f9SFangrui Song static ``std::random_device`` for seeding the random number generator. This 49a45d2287SDanila Kutenin guarantees the same stability guarantee within a run but not through different 50a45d2287SDanila Kutenin runs, for example, for tests become flaky and eventually be seen as broken. 51a45d2287SDanila Kutenin For platforms which do not support ASLR, the seed is fixed during build. 52a45d2287SDanila Kutenin* The users can fix the seed of the random number generator by providing 530a1c94f9SFangrui Song ``_LIBCPP_RANDOMIZE_UNSPECIFIED_STABILITY_SEED=seed`` definition. 54a45d2287SDanila Kutenin 55a45d2287SDanila KuteninThis comes with some side effects if any of the flags is on: 56a45d2287SDanila Kutenin 57a45d2287SDanila Kutenin* Computation penalty, we think users are OK with that if they use this feature. 58a45d2287SDanila Kutenin* Non reproducible results if they don't use the fixed seed. 59a45d2287SDanila Kutenin 60a45d2287SDanila Kutenin 61a45d2287SDanila KuteninImpact 62a45d2287SDanila Kutenin------------------ 63a45d2287SDanila Kutenin 64a45d2287SDanila KuteninGoogle has measured couple of thousands of tests to be dependent on the 65a45d2287SDanila Kuteninstability of sorting and selection algorithms. As we also plan on updating 66a45d2287SDanila Kutenin(or least, providing under flag more) sorting algorithms, this effort helps 67a45d2287SDanila Kutenindoing it gradually and sustainably. This is also bad for users to depend on the 68a45d2287SDanila Kuteninunspecified behavior in their tests, this effort helps to turn this flag in 69a45d2287SDanila Kutenindebug mode. 70a45d2287SDanila Kutenin 71a45d2287SDanila KuteninPotential breakages 72a45d2287SDanila Kutenin------------------- 73a45d2287SDanila Kutenin 74a45d2287SDanila KuteninNone if the flag is off. If the flag is on, it may lead to some non-reproducible 75a45d2287SDanila Kuteninresults, for example, for caching. 76a45d2287SDanila Kutenin 77a45d2287SDanila KuteninCurrently supported randomization 78a45d2287SDanila Kutenin--------------------------------- 79a45d2287SDanila Kutenin 800a1c94f9SFangrui Song* ``std::sort``, there is no guarantee on the order of equal elements 810a1c94f9SFangrui Song* ``std::partial_sort``, there is no guarantee on the order of equal elements and 82a45d2287SDanila Kutenin on the order of the remaining part 830a1c94f9SFangrui Song* ``std::nth_element``, there is no guarantee on the order from both sides of the 84a45d2287SDanila Kutenin partition 85a45d2287SDanila Kutenin 86a45d2287SDanila KuteninPatches welcome. 87