entt: Performance regression in basic_registry::ctx()

Hello! I have been working on a project for a while using EnTT 3.4.0, and recently upgraded to EnTT 3.8.1. The code migration was not very difficult (thanks!), however there seem to have been a significant performance regression in the basic_registry::ctx() function.

Below are excerpts of a linux perf output before and after migration. These were collected in Debug mode with no optimisation to preserve the full call graph, but the relative performance hit from switching to 3.8.1 is about the same (~50% overall increased runtime) in both Debug and Release configurations.

There is quite a lot of changes listed in the release notes, so I can’t pin point which could have triggered this. But from the call graph, it seems that ctx() is now using any under the hood, and that appears to be the main cause of the overhead. Is this an expected regression, i.e., should I accept that ctx() is now slower and cache the output rather than query it all the time?

EnTT 3.4.0:

--6.78%--entt::basic_registry<entt::entity>::ctx<game::hex_size>
 |    
  --6.71%--entt::basic_registry<entt::entity>::try_ctx<game::hex_size>
   |    
    --5.55%--std::find_if<__gnu_cxx::__normal_iterator<entt::basic_registry<entt::entity>::variable_data const*, std::vector<entt::basic_registry<entt::entity>::variable_data, std::allocator<en>
     |    
      --5.37%--std::__find_if<__gnu_cxx::__normal_iterator<entt::basic_registry<entt::entity>::variable_data const*, std::vector<entt::basic_registry<entt::entity>::variable_data, std:>
       |    
       --4.83%--std::__find_if<__gnu_cxx::__normal_iterator<entt::basic_registry<entt::entity>::variable_data const*, std::vector<entt::basic_registry<entt::entity>::variable>
        |    
         --3.29%--__gnu_cxx::__ops::_Iter_pred<entt::basic_registry<entt::entity>::try_ctx<game::hex_size>() const::{lambda(auto:1&&)#1}>::operator()<__gnu_cxx::__no>
          |    
           --2.26%--entt::basic_registry<entt::entity>::try_ctx<game::hex_size>() const::{lambda(auto:1&&)#1}::operator()<entt::basic_registry<entt::entity>>

EnTT 3.8.1:

--21.46%--entt::basic_registry<entt::entity>::ctx<game::hex_size>
 |    
 |--19.28%--std::find_if<__gnu_cxx::__normal_iterator<entt::basic_any<0ul, 16ul> const*, std::vector<entt::basic_any<0ul, 16ul>, std::allocator<entt::basic_any<0ul, 16ul> > > >, entt::basic_registry<ent>
 | |    
 |  --18.87%--std::__find_if<__gnu_cxx::__normal_iterator<entt::basic_any<0ul, 16ul> const*, std::vector<entt::basic_any<0ul, 16ul>, std::allocator<entt::basic_any<0ul, 16ul> > > >, __gnu_cxx::>
 |   |    
 |    --18.66%--std::__find_if<__gnu_cxx::__normal_iterator<entt::basic_any<0ul, 16ul> const*, std::vector<entt::basic_any<0ul, 16ul>, std::allocator<entt::basic_any<0ul, 16ul> > > >, >
 |     |    
 |      --17.19%--__gnu_cxx::__ops::_Iter_pred<entt::basic_registry<entt::entity>::ctx<game::hex_size>() const::{lambda(auto:1&&)#1}>::operator()<__gnu_cxx::__normal_iterator<>
 |       |    
 |       |--16.27%--entt::basic_registry<entt::entity>::ctx<game::hex_size>() const::{lambda(auto:1&&)#1}::operator()<entt::basic_any<0ul, 16ul> const&>
 |       | |    
 |       | |--12.99%--entt::basic_any<0ul, 16ul>::type
 |       | | |    
 |       | | |--1.77%--entt::type_info::type_info
 |       | | | |    
 |       | | | |--0.72%--entt::type_info::type_info
 |       | | | |    
 |       | | |  --0.59%--std::basic_string_view<char, std::char_traits<char> >::basic_string_view
 |       | | |    
 |       | | |--0.69%--entt::basic_any<0ul, 16ul>::basic_vtable<game::editor_mode>
 |       | | |    
 |       | | |--0.66%--entt::basic_any<0ul, 16ul>::basic_vtable<game::current_player>
 |       | | | |    
 |       | | |  --0.51%--entt::type_id<game::current_player>
 |       | | |    
 |       | | |--0.66%--entt::basic_any<0ul, 16ul>::basic_vtable<game::hex_size>
 |       | | |    
 |       | | |--0.64%--entt::basic_any<0ul, 16ul>::basic_vtable<game::game_paused>
 |       | | |    
 |       | | |--0.64%--entt::basic_any<0ul, 16ul>::basic_vtable<game::status_list>
 |       | | |    
 |       | | |--0.63%--entt::basic_any<0ul, 16ul>::basic_vtable<game::stage>
 |       | | |    
 |       | | |--0.62%--entt::basic_any<0ul, 16ul>::basic_vtable<trade::cargo_container_template_list>
 |       | | |    
 |       | | |--0.59%--entt::basic_any<0ul, 16ul>::basic_vtable<game::tool_list>
 |       | | |    
 |       | | |--0.58%--entt::basic_any<0ul, 16ul>::basic_vtable<game::ship_template_list>
 |       | | |    
 |       | | |--0.57%--entt::basic_any<0ul, 16ul>::basic_vtable<game::time>
 |       | | |    
 |       | | |--0.56%--entt::basic_any<0ul, 16ul>::basic_vtable<starsystem::delta_network>
 |       | | |    
 |       | | |--0.56%--entt::basic_any<0ul, 16ul>::basic_vtable<trade::goods_list>
 |       | | |    
 |       | | |--0.56%--entt::basic_any<0ul, 16ul>::basic_vtable<orders::order_template_list>
 |       | | |    
 |       | | |--0.54%--entt::basic_any<0ul, 16ul>::basic_vtable<game::current_tool>
 |       | | |    
 |       | | |--0.53%--entt::basic_any<0ul, 16ul>::basic_vtable<game::viewed_starsystem>
 |       | | |    
 |       | | |--0.52%--entt::basic_any<0ul, 16ul>::basic_vtable<game::view_zoom_pan>
 |       | | |    
 |       | |  --0.52%--entt::basic_any<0ul, 16ul>::basic_vtable<game::hovered>
 |       | | 
 |       |  --0.94%--entt::type_info::operator==
 |       | 
 |        --0.63%--__gnu_cxx::__normal_iterator<entt::basic_any<0ul, 16ul> const*, std::vector<entt::basic_any<0ul, 16ul>, std::allocator<entt::basic_any<0ul, 16ul> >>
 | 
  --1.28%--entt::any_cast<game::hex_size const&, 0ul, 16ul>
   |    
    --1.20%--entt::any_cast<game::hex_size const, 0ul, 16ul>
     |    
      --0.70%--entt::basic_any<0ul, 16ul>::type

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 20 (20 by maintainers)

Commits related to this issue

Most upvoted comments

Yep, that commit fixes the issue for me! (edit: thank you for spending the time to look into this 😃)

Yet another commit on wip, this time it’s close to your last suggestion. Briefly, I copied the approach of the standard library for which typeid returns objects with static storage duration. Then I’ve added a top-level pointer to a type_info in any. Can I ask you to give it a try and let me know? It would be really great.