wy-ei commented on PR #768:
URL: 
https://github.com/apache/incubator-kvrocks/pull/768#issuecomment-1211606587

   @PragmaTwice 
   
   Throwing exception is more than 100 times slower than return error code, If 
the probability of throwing exception is less than 1/100, the cost of throwing 
exception can be ignored.
   
   I run the benchmark in  [1] on my machine, here is the result:
   
   ```
   Run on (8 X 24.1247 MHz CPU s)
   CPU Caches:
     L1 Data 64 KiB
     L1 Instruction 128 KiB
     L2 Unified 4096 KiB (x8)
   Load Average: 4.60, 3.61, 3.14
   ----------------------------------------------------------------------
   Benchmark                            Time             CPU   Iterations
   ----------------------------------------------------------------------
   BM_exitWithBasicException          356 ns          356 ns      1949354
   BM_exitWithMessageException        423 ns          412 ns      1812467
   BM_exitWithReturn                 3.09 ns         3.09 ns    218084841
   BM_exitWithErrorCode              3.04 ns         3.04 ns    233471081
   ```
   
   In this benchmark, the exception was thrown  every two function calls, but 
in real situation, exception unlikely be thrown this often.
   
   I change the benchmark code to make the exception be thrown every 200 
function calls. (change the variable `randomRange` to 200),and run benchmark 
again, here is the result:
   
   ```
   Run on (8 X 24.1216 MHz CPU s)
   CPU Caches:
     L1 Data 64 KiB
     L1 Instruction 128 KiB
     L2 Unified 4096 KiB (x8)
   Load Average: 3.45, 2.54, 3.10
   ----------------------------------------------------------------------
   Benchmark                            Time             CPU   Iterations
   ----------------------------------------------------------------------
   BM_exitWithBasicException         6.78 ns         6.78 ns     75871712
   BM_exitWithMessageException       7.03 ns         7.03 ns     99061744
   BM_exitWithReturn                 2.98 ns         2.98 ns    235143942
   BM_exitWithErrorCode              2.98 ns         2.98 ns    234956097
   ```
   
   Since throwing exception is a small part of the code, in real situation, I 
think the cost of exception is not a big problem.
   
   > So I don't think it's a good idea to use exceptions on some execution path 
that is not a very low probability error or is user  controllable.
   
   If user input cause error,  then error may occur with high probability, use 
exception would be inefficient. In this situation, some pre check code can be 
added to return error fast,  and comparing with disk and network read and 
write, the cost of exception is not the main part. 
   
   > Another defect is that C++ does not have checked exception, this makes 
exception flows not easy to maintain. In addition, it is not easy to ensure the 
exception safety of the program, which requires the programmer to have a deep 
background knowledge of C++.
   
   C++ do not force user catch the exception, but if you miss an exception the 
process will crash. We can ignore an error status, and something weird 
happened, but we didn't known the reason. If we keep using RAII, the exception 
safety can almost be ensure. 
   
   I mentioned exception here because I was think is there another way to deal 
with error instead Status. I think both exception and status are ok. But using 
exception in kvrocks will break the consistency of the function design (return 
Status and pass result as a pointer in last argument), I think this will be a 
big change, and I except this won't happed in the near future. 
   
   I was off topic for a long time,  Back to Status and StatusOr.
   
   In kvrocks, Status class is a large object which include a std::string in 
it.  The Status class implemented in leveldb only take 8 bytes (only one member 
which is  const char *state_).  If status is ok, state_ is nullptr, if status 
is not ok, the state_ store the error code and error message. If we change the 
Status implementation in kvrocks to the leveldb way, the size of Status is not 
a problem. 
   
   Another problem of Status for me is it occupy the place of the return value, 
we must pass a pointer to take the return value. Golang solve this problem by 
returning multi value.  A sample and easily understand way is return a tuple  
or another Class will contain return value T and status.
   
   For StatusOr I have one question. StatusOr use a char[] to store T or 
Status, I don't known why, why don't use union?
   
   C++23 std::expected [2] is used to contains expected value or an error, does 
this a more generic way, Can we implement same thing like this. We can combine 
Status and the expected class do the things StatusOr does.
   
   
   [1] https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp
   [2] https://en.cppreference.com/w/cpp/header/expected


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to