]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common: optimize assert_data_ctx passing in ceph_assert()
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Fri, 14 Mar 2025 01:55:58 +0000 (01:55 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 18 Mar 2025 20:46:51 +0000 (20:46 +0000)
\### After
```
0000000000e58600 <PeeringState::clear_blocked_outgoing()>:
  e58600:       48 83 ec 18             sub    $0x18,%rsp
  e58604:       48 83 bf e0 00 00 00    cmpq   $0x0,0xe0(%rdi)
  e5860b:       00
  e5860c:       0f 84 fc 0f b0 ff       je     95960e <PeeringState::clear_blocked_outgoing() [clone .cold]+0x14>
  e58612:       80 bf 40 01 00 00 00    cmpb   $0x0,0x140(%rdi)
  e58619:       0f 84 db 0f b0 ff       je     9595fa <PeeringState::clear_blocked_outgoing() [clone .cold]>
  e5861f:       80 bf 18 01 00 00 00    cmpb   $0x0,0x118(%rdi)
  e58626:       75 08                   jne    e58630 <PeeringState::clear_blocked_outgoing()+0x30>
  e58628:       48 83 c4 18             add    $0x18,%rsp
  e5862c:       c3                      retq
  e5862d:       0f 1f 00                nopl   (%rax)
  e58630:       c6 87 18 01 00 00 00    movb   $0x0,0x118(%rdi)
  e58637:       48 8b bf f8 00 00 00    mov    0xf8(%rdi),%rdi
  e5863e:       48 83 c4 18             add    $0x18,%rsp
  e58642:       e9 89 bc ff ff          jmpq   e542d0 <std::_Rb_tree<int, std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > >, std::_Select1st<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >, std::less<int>, std::allocator<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >*) [clone .isra.0]>
  e58647:       90                      nop
  e58648:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  e5864f:       00
```

\### Vanilla main
Loading of `assert_data_ctx` was `unlikely` bot not `cold`:

```
0000000000e3cf90 <PeeringState::clear_blocked_outgoing()>:
  e3cf90:       48 83 ec 08             sub    $0x8,%rsp
  e3cf94:       48 83 bf e0 00 00 00    cmpq   $0x0,0xe0(%rdi)
  e3cf9b:       00
  e3cf9c:       74 3d                   je     e3cfdb <PeeringState::clear_blocked_outgoing()+0x4b>
  e3cf9e:       80 bf 40 01 00 00 00    cmpb   $0x0,0x140(%rdi)
  e3cfa5:       74 28                   je     e3cfcf <PeeringState::clear_blocked_outgoing()+0x3f>
  e3cfa7:       80 bf 18 01 00 00 00    cmpb   $0x0,0x118(%rdi)
  e3cfae:       75 08                   jne    e3cfb8 <PeeringState::clear_blocked_outgoing()+0x28>
  e3cfb0:       48 83 c4 08             add    $0x8,%rsp
  e3cfb4:       c3                      retq
  e3cfb5:       0f 1f 00                nopl   (%rax)
  e3cfb8:       c6 87 18 01 00 00 00    movb   $0x0,0x118(%rdi)
  e3cfbf:       48 8b bf f8 00 00 00    mov    0xf8(%rdi),%rdi
  e3cfc6:       48 83 c4 08             add    $0x8,%rsp
  e3cfca:       e9 01 bd ff ff          jmpq   e38cd0 <std::_Rb_tree<int, std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > >, std::_Select1st<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >, std::less<int>, std::allocator<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > > >::_M_erase(std::_Rb_tree_node<std::pair<int const, std::vector<boost::intrusive_ptr<Message>, std::allocator<boost::intrusive_ptr<Message> > > > >*) [clone .isra.0]>
  e3cfcf:       48 8d 3d aa 0b 29 01    lea    0x1290baa(%rip),%rdi        # 20cdb80 <PeeringState::clear_blocked_outgoing()::assert_data_ctx>
  e3cfd6:       e8 64 6c b6 ff          callq  9a3c3f <ceph::__ceph_assert_fail(ceph::assert_data const&)>
  e3cfdb:       48 8d 3d be 0b 29 01    lea    0x1290bbe(%rip),%rdi        # 20cdba0 <PeeringState::clear_blocked_outgoing()::assert_data_ctx>
  e3cfe2:       e8 58 6c b6 ff          callq  9a3c3f <ceph::__ceph_assert_fail(ceph::assert_data const&)>
  e3cfe7:       90                      nop
  e3cfe8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  e3cfef:       00
```

Fixes: https://tracker.ceph.com/issues/70476
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/include/ceph_assert.h

index f9dca86d9ff10a30e9184ec3fe435d32ec507fb0..f0e87073946bfa192d003bf18b58cc8595b114a7 100644 (file)
@@ -52,6 +52,10 @@ struct assert_data {
 
 extern void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *function);
 extern void __ceph_assert_fail(const assert_data &ctx);
+template <const assert_data* AssertCtxV>
+[[gnu::noinline, gnu::cold]] static void __ceph_assert_fail()  {
+  __ceph_assert_fail(*AssertCtxV);
+}
 
 extern void __ceph_assertf_fail(const char *assertion, const char *file, int line, const char *function, const char* msg, ...);
 extern void __ceph_assert_warn(const char *assertion, const char *file, int line, const char *function);
@@ -98,11 +102,14 @@ using namespace ceph;
   } while (false)
 #else
 #define ceph_assert(expr)                                                      \
-  do { static const ceph::assert_data assert_data_ctx = \
-   {__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION}; \
-   ((expr) \
-   ? _CEPH_ASSERT_VOID_CAST (0) \
-    : ::ceph::__ceph_assert_fail(assert_data_ctx)); } while(false)
+  do { \
+    static const auto func_name = __CEPH_ASSERT_FUNCTION; \
+    [] (const bool eval) { \
+    static const ceph::assert_data assert_data_ctx = \
+    {__STRING(expr), __FILE__, __LINE__, func_name}; \
+    ((eval) \
+    ? _CEPH_ASSERT_VOID_CAST (0) \
+    : ::ceph::__ceph_assert_fail<&assert_data_ctx>()); }((bool)(expr)); } while(false)
 #endif
 
 // this variant will *never* get compiled out to NDEBUG in the future.
@@ -116,11 +123,14 @@ using namespace ceph;
   } while(false)
 #else
 #define ceph_assert_always(expr)                                                       \
-  do { static const ceph::assert_data assert_data_ctx = \
-   {__STRING(expr), __FILE__, __LINE__, __CEPH_ASSERT_FUNCTION}; \
-   ((expr) \
-   ? _CEPH_ASSERT_VOID_CAST (0) \
-    : ::ceph::__ceph_assert_fail(assert_data_ctx)); } while(false)
+  do { \
+    static const auto func_name = __CEPH_ASSERT_FUNCTION; \
+    [] (const bool eval) { \
+    static const ceph::assert_data assert_data_ctx = \
+    {__STRING(expr), __FILE__, __LINE__, func_name}; \
+    ((eval) \
+    ? _CEPH_ASSERT_VOID_CAST (0) \
+    : ::ceph::__ceph_assert_fail<&assert_data_ctx>()); }((bool)(expr)); } while(false)
 #endif
 
 // Named by analogy with printf.  Along with an expression, takes a format