Storing and Rethrowing Exceptions

Performance Considerations with std::exception_ptr

What are the performance implications of using std::exception_ptr?

Abstract art representing computer programming

Using std::exception_ptr to capture, store, and rethrow exceptions does have some performance implications that are worth considering:

  1. Capturing exceptions: When an exception is captured into a std::exception_ptr using std::current_exception(), the exception object is copied. This copy operation can have a performance cost, especially if the exception object is large or has a complex copy constructor.
  2. Memory allocation: Capturing an exception into a std::exception_ptr involves allocating memory on the heap for the copied exception object. This memory allocation can have a performance impact, particularly if exceptions are frequently captured.
  3. Rethrowing exceptions: Rethrowing an exception using std::rethrow_exception() is generally as efficient as throwing the exception directly. However, there is a small overhead due to the indirection through the std::exception_ptr.
  4. Exception handling in general: Exception handling itself has a performance cost, regardless of whether std::exception_ptr is used. When an exception is thrown, the stack must be unwound to find the appropriate catch block, which can be expensive.

Here's an example that demonstrates the performance difference between rethrowing an exception directly and using std::exception_ptr:

#include <chrono>
#include <exception>
#include <iostream>

void throwException() {
  throw std::runtime_error("Exception");
}

void rethrowDirect() {
  try {
    throwException();
  } catch (...) {
    throw;
  }
}

void rethrowPtr() {
  try {
    throwException();
  } catch (...) {
    std::exception_ptr eptr =
      std::current_exception();
    std::rethrow_exception(eptr);
  }
}

int main() {
  using namespace std::chrono;
  auto start = high_resolution_clock::now();
  try {
    rethrowDirect();
  } catch (...) {}
  auto end = high_resolution_clock::now();
  duration<double, std::micro> elapsed =
    end - start;
  std::cout << "Direct rethrow took "
    << elapsed.count() << "us\n";

  start = high_resolution_clock::now();
  try {
    rethrowPtr();
  } catch (...) {}
  end = high_resolution_clock::now();
  elapsed = end - start;
  std::cout << "Rethrow using std::exception_ptr"
    " took " << elapsed.count() << "us\n";
}
Direct rethrow took 1021.8us
Rethrow using std::exception_ptr took 1798.6us

In this example, we measure the time taken to rethrow an exception directly (rethrowDirect()) and to rethrow it using std::exception_ptr (rethrowPtr()). The results show that using std::exception_ptr is slightly slower due to the additional overhead.

However, it's important to note that the performance difference is usually negligible unless exceptions are used very frequently. The benefits of using std::exception_ptr, such as the ability to store and transfer exceptions, often outweigh the small performance cost.

As with all performance considerations, it's important to profile and measure in the context of your specific application to determine if the use of std::exception_ptr has a significant impact.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved