xref: /llvm-project/libcxx/docs/DesignDocs/UnspecifiedBehaviorRandomization.rst (revision da6a1f61d94c05e36d7797b198bc55ac6486f4ff)
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