[cfe-commits] [libcxxabi] r148083 - /libcxxabi/trunk/test/dynamic_cast_stress.cpp

Howard Hinnant hhinnant at apple.com
Thu Jan 12 17:22:31 PST 2012


Author: hhinnant
Date: Thu Jan 12 19:22:31 2012
New Revision: 148083

URL: http://llvm.org/viewvc/llvm-project?rev=148083&view=rev
Log:
Enclosed is a stress test for dynamic_cast.  It stresses both libc++abi, and clang itself.  It creates a ridiculously large class hierarchy using variadic templates.  You can specify both the width and depth of the class hierarchy.  And you can specify whether the cast is to the actual run time type, or to an intermediate layer in the class.  About 1/3 of the time I compile this, it crashes the compiler.  There seems to be an uninitialized area of memory, and I'm probably blowing past an assumption on class hierarchy size within clang (and understandably so). I can get it work most of the time with a class hierarchy width of 20 and a depth of 7.  I'm making timings with both -O3 and -Os, using both cast to root and cast to intermediate, on both libc++abi, and gcc's dynamic_cast.  I've put the results in a comment/table at the bottom of the test.

Added:
    libcxxabi/trunk/test/dynamic_cast_stress.cpp

Added: libcxxabi/trunk/test/dynamic_cast_stress.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/dynamic_cast_stress.cpp?rev=148083&view=auto
==============================================================================
--- libcxxabi/trunk/test/dynamic_cast_stress.cpp (added)
+++ libcxxabi/trunk/test/dynamic_cast_stress.cpp Thu Jan 12 19:22:31 2012
@@ -0,0 +1,81 @@
+//===------------------------- dynamic_cast_stress.cpp --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cassert>
+#include <tuple>
+#include <chrono>
+#include <iostream>
+
+template <std::size_t Indx, std::size_t Depth>
+struct C
+    : public virtual C<Indx, Depth-1>,
+      public virtual C<Indx+1, Depth-1>
+{
+    virtual ~C() {}
+};
+
+template <std::size_t Indx>
+struct C<Indx, 0>
+{
+    virtual ~C() {}
+};
+
+template <std::size_t Indx, std::size_t Depth>
+struct B
+    : public virtual C<Indx, Depth-1>,
+      public virtual C<Indx+1, Depth-1>
+{
+};
+
+template <class Indx, std::size_t Depth>
+struct makeB;
+
+template <std::size_t ...Indx, std::size_t Depth>
+struct makeB<std::__tuple_indices<Indx...>, Depth>
+    : public B<Indx, Depth>...
+{
+};
+
+template <std::size_t Width, std::size_t Depth>
+struct A
+    : public makeB<typename std::__make_tuple_indices<Width>::type, Depth>
+{
+};
+
+void test()
+{
+    typedef std::chrono::high_resolution_clock Clock;
+    typedef std::chrono::duration<double, std::micro> US;
+    const std::size_t Width = 20;
+    const std::size_t Depth = 7;
+    A<Width, Depth> a;
+    typedef B<Width/2, Depth> Destination;
+//    typedef A<Width, Depth> Destination;
+    auto t0 = Clock::now();
+    Destination* b = dynamic_cast<Destination*>((C<Width/2, 0>*)&a);
+    auto t1 = Clock::now();
+    std::cout << US(t1-t0).count() << " microseconds\n";
+    assert(b != 0);
+}
+
+int main()
+{
+    test();
+}
+
+/*
+Timing results I'm seeing (median of 3 microseconds):
+
+                          libc++abi    gcc's dynamic_cast
+B<Width/2, Depth> -O3      64.214         93.190           libc++abi 45% faster
+B<Width/2, Depth> -Os      79.520         94.103           libc++abi 18% faster
+A<Width, Depth>   -O3      11.833         33.134           libc++abi 180% faster
+A<Width, Depth>   -Os      14.663         31.553           libc++abi 115% faster
+
+*/





More information about the cfe-commits mailing list