X-Git-Url: https://git.proxmox.com/?p=ceph.git;a=blobdiff_plain;f=ceph%2Fsrc%2Fboost%2Flibs%2Fleaf%2Fbenchmark%2Fbenchmark.md;h=0ae9b3328e1747debbe6402650e6bbd42baa329e;hp=e1dc49052cd390de1c229c74999126db08ff90f2;hb=1e59de90020f1d8d374046ef9cca56ccd4e806e2;hpb=bd41e436e25044e8e83156060a37c23cb661c364 diff --git a/ceph/src/boost/libs/leaf/benchmark/benchmark.md b/ceph/src/boost/libs/leaf/benchmark/benchmark.md index e1dc49052..0ae9b3328 100644 --- a/ceph/src/boost/libs/leaf/benchmark/benchmark.md +++ b/ceph/src/boost/libs/leaf/benchmark/benchmark.md @@ -13,9 +13,9 @@ LEAF serves a similar purpose to other error handling libraries, but its design The main design difference is that when using LEAF, error objects are not communicated in return values. In case of a failure, the `leaf::result` object transports only an `int`, the unique error ID. -Error objects skip the error-neutral functions in the call stack and get moved directly to the the error-handling scope that needs them. This mechanism does not depend on RVO or any other optimization: as soon as the program passes an error object to LEAF, it moves it to the correct error handling scope. +Error objects skip the error neutral functions in the call stack and get moved directly to the the error handling scope that needs them. This mechanism does not depend on RVO or any other optimization: as soon as the program passes an error object to LEAF, it moves it to the correct error handling scope. -Other error-handling libraries instead couple the static type of the return value of *all* error-neutral functions with the error type an error-reporting function may return. This approach suffers from the same problems as statically-enforced exception specifications: +Other error handling libraries instead couple the static type of the return value of *all* error neutral functions with the error type an error reporting function may return. This approach suffers from the same problems as statically-enforced exception specifications: * It's difficult to use in polymorphic function calls, and * It impedes interoperability between the many different error types any non-trivial program must handle. @@ -122,11 +122,11 @@ Which on clang 9 outputs: ```x86asm val(): - mov eax, 42 - ret + mov eax, 42 + ret main: - mov eax, 42 - ret + mov eax, 42 + ret ``` It does not appear that anything like this is occurring in our case, but it is still a possibility. @@ -150,48 +150,48 @@ leaf::result g() } ``` -Generates this code on clang ([Godbolt](https://godbolt.org/z/aMh4zo)): +Generates this code on clang ([Godbolt](https://godbolt.org/z/v58drTPhq)): ```x86asm g(): # @g() - push rbx - sub rsp, 32 - mov rbx, rdi - mov rdi, rsp - call f() - mov eax, dword ptr [rsp + 16] - mov ecx, eax - and ecx, 3 - cmp ecx, 2 - je .LBB0_3 - cmp ecx, 3 - jne .LBB0_4 - mov eax, dword ptr [rsp] - add eax, 1 - mov dword ptr [rbx], eax - mov eax, 3 - jmp .LBB0_4 + push rbx + sub rsp, 32 + mov rbx, rdi + lea rdi, [rsp + 8] + call f() + mov eax, dword ptr [rsp + 24] + mov ecx, eax + and ecx, 3 + cmp ecx, 3 + jne .LBB0_1 + mov eax, dword ptr [rsp + 8] + add eax, 1 + mov dword ptr [rbx], eax + mov eax, 3 + jmp .LBB0_3 +.LBB0_1: + cmp ecx, 2 + jne .LBB0_3 + mov rax, qword ptr [rsp + 8] + mov qword ptr [rbx], rax + mov rax, qword ptr [rsp + 16] + mov qword ptr [rbx + 8], rax + mov eax, 2 .LBB0_3: - movaps xmm0, xmmword ptr [rsp] - mov qword ptr [rsp + 8], 0 - movups xmmword ptr [rbx], xmm0 - mov qword ptr [rsp], 0 - mov eax, 2 -.LBB0_4: - mov dword ptr [rbx + 16], eax - mov rax, rbx - add rsp, 32 - pop rbx - ret + mov dword ptr [rbx + 16], eax + mov rax, rbx + add rsp, 32 + pop rbx + ret ``` > Description: > > * The happy path can be recognized by the `add eax, 1` instruction generated for `x + 1`. > -> * `.LBB0_4`: Regular failure; the returned `result` object holds only the `int` discriminant. +> * `.LBB0_3`: Regular failure; the returned `result` object holds only the `int` discriminant. > -> * `.LBB0_3`: Failure; the returned `result` holds the `int` discriminant and a `std::shared_ptr` (used to hold error objects transported from another thread). +> * `.LBB0_1`: Failure; the returned `result` holds the `int` discriminant and a `std::shared_ptr` (used to hold error objects transported from another thread). Note that `f` is undefined, hence the `call` instruction. Predictably, if we provide a trivial definition for `f`: @@ -212,10 +212,10 @@ We get: ```x86asm g(): # @g() - mov rax, rdi - mov dword ptr [rdi], 43 - mov dword ptr [rdi + 16], 3 - ret + mov rax, rdi + mov dword ptr [rdi], 43 + mov dword ptr [rdi + 16], 3 + ret ``` With a less trivial definition of `f`: @@ -236,32 +236,32 @@ leaf::result g() } ``` -We get ([Godbolt](https://godbolt.org/z/nezE7s)): +We get ([Godbolt](https://godbolt.org/z/87Kezzrs4)): ```x86asm g(): # @g() - push rbx - mov rbx, rdi - call rand - test al, 1 - jne .LBB1_2 - mov eax, 4 - lock xadd dword ptr [rip + boost::leaf::leaf_detail::id_factory::counter], eax - add eax, 4 - mov dword ptr fs:[boost::leaf::leaf_detail::id_factory::current_id@TPOFF], eax - and eax, -4 - or eax, 1 - mov dword ptr [rbx + 16], eax - mov rax, rbx - pop rbx - ret + push rbx + mov rbx, rdi + call rand + test al, 1 + jne .LBB1_2 + mov eax, 4 + lock xadd dword ptr [rip + boost::leaf::leaf_detail::id_factory::counter], eax + add eax, 4 + mov dword ptr fs:[boost::leaf::leaf_detail::id_factory::current_id@TPOFF], eax + and eax, -4 + or eax, 1 + mov dword ptr [rbx + 16], eax + mov rax, rbx + pop rbx + ret .LBB1_2: - mov dword ptr [rbx], 43 - mov eax, 3 - mov dword ptr [rbx + 16], eax - mov rax, rbx - pop rbx - ret + mov dword ptr [rbx], 43 + mov eax, 3 + mov dword ptr [rbx + 16], eax + mov rax, rbx + pop rbx + ret ``` Above, the call to `f()` is inlined: @@ -285,7 +285,7 @@ The benchmark matrix has 2 dimensions: Now, transporting a large error object might seem unusual, but this is only because it is impractical to return a large object as *the* return value in case of an error. LEAF has two features that make communicating any, even large error objects, practical: -* The return type of error-neutral functions is not coupled with the error object types that may be reported. This means that in case of a failure, any function can easily contribute any error information it has available. +* The return type of error neutral functions is not coupled with the error object types that may be reported. This means that in case of a failure, any function can easily contribute any error information it has available. * LEAF will only bother with transporting a given error object if an active error handling scope needs it. This means that library functions can and should contribute any and all relevant information when reporting a failure, because if the program doesn't need it, it will simply be discarded. @@ -297,23 +297,22 @@ Now, transporting a large error object might seem unusual, but this is only beca ## Godbolt -Godbolt has built-in support for Boost (Outcome), but LEAF and `tl::expected` both provide a single header, which makes it very easy to use them online as well. To see the generated code for the benchmark program, you can copy and paste the following into Godbolt: +Godbolt has built-in support for Boost (Outcome/LEAF), but `tl::expected` both provide a single header, which makes it very easy to use them online as well. To see the generated code for the benchmark program, you can copy and paste the following into Godbolt: -`leaf::result` ([godbolt](https://godbolt.org/z/Thdq1d)) +`leaf::result` ([godbolt](https://godbolt.org/z/1hqqnfhMf)) ```c++ -#include "https://raw.githubusercontent.com/boostorg/leaf/master/include/boost/leaf.hpp" #include "https://raw.githubusercontent.com/boostorg/leaf/master/benchmark/deep_stack_leaf.cpp" ``` -`tl::expected` ([godbolt](https://godbolt.org/z/sHwtTU)) +`tl::expected` ([godbolt](https://godbolt.org/z/6dfcdsPcc)) ```c++ #include "https://raw.githubusercontent.com/TartanLlama/expected/master/include/tl/expected.hpp" #include "https://raw.githubusercontent.com/boostorg/leaf/master/benchmark/deep_stack_other.cpp" ``` -`outcome::result` ([godbolt](https://godbolt.org/z/ZrfRRA)) +`outcome::result` ([godbolt](https://godbolt.org/z/jMEfGMrW9)) ```c++ #define BENCHMARK_WHAT 1 @@ -331,7 +330,7 @@ To build both versions of the benchmark program, the compilers are invoked using In addition, the LEAF version is compiled with: -* `-DBOOST_LEAF_DIAGNOSTICS=0`: Disable diagnostic information for error objects not recognized by the program. This is a debugging feature, see [Configuration Macros](https://boostorg.github.io/leaf/#_configuration_macros). +* `-DBOOST_LEAF_CFG_DIAGNOSTICS=0`: Disable diagnostic information for error objects not recognized by the program. This is a debugging feature, see [Configuration Macros](https://boostorg.github.io/leaf/#configuration). ## Results