4

I have a very basic example, just joining several strings into a bigger string, with a separator. I have implemented it using ranges and using a raw for loop, and measured performance using google benchmark. The ranges-v3 version is much slower than the for loop version, and I don't understand why.

Why is the ranges version slower? What is the extra work is doing compared to the for loop version?

#include <string>
#include <span>
#include <range/v3/view.hpp>
#include <range/v3/range/conversion.hpp>


struct Element {
    std::string name;
    std::string some_other_data_not_relevant_here;
};


std::string stack_to_path(std::span<const Element> stack) {
    return stack | ranges::views::transform(&Element::name)
                 | ranges::views::join('/')
                 | ranges::to<std::string>;
}

std::string stack_to_path_naive(std::span<const Element> stack) {
    std::string r;
    for (const Element& el : stack) {
        if (!r.empty())
            r += '/';
        r += el.name;
    }
    return r;
}

https://godbolt.org/z/6jWW9chhE

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
jjcasmar
  • 1,387
  • 1
  • 18
  • 30
  • 1
    Are you building/testing with compiler optimizations enabled? – Jesper Juhl Jul 24 '23 at 11:08
  • 1
    Yes, for building I am using CMake, with Release CMAKE_BUILD_TYPE and march=native also applied. Also, in the godbolt test is with -O3 – jjcasmar Jul 24 '23 at 11:14
  • No-one have claimed that using ranges would automatically be more efficient or faster than using more naive solutions. It does give you greater flexibility to do complicated things in an easier way, and sometimes it might be more efficient. – Some programmer dude Jul 24 '23 at 11:16
  • 4
    No one has claimed it should be faster, but people has claimed its a 0 cost abstractions, and this is for sure not a 0 cost abstraction – jjcasmar Jul 24 '23 at 11:25
  • *...but people has claimed its a 0 cost abstractions...* You should ask those people. – Eljay Jul 24 '23 at 11:29
  • `ranges::views::join('/')` is a lazy view, so need some bookkeeping. – Jarod42 Jul 24 '23 at 11:30
  • @Eljay well, I am asking in SO, I usually ask codings questions here. I am trying to understand why ranges-v3 in this case is so much slower. Do you really think this is not the right forum to ask this kind of questions? – jjcasmar Jul 24 '23 at 11:31
  • libstdc++ `` result -> [demo](https://godbolt.org/z/o6xnGoxoh). – 康桓瑋 Jul 24 '23 at 11:42
  • @康桓瑋 thanks for the updated demo. Still much slower with the libstdc++ implementation though :-( – jjcasmar Jul 24 '23 at 11:45
  • In that case, the answer to your question is "those people" are wrong, ranges is not a zero cost abstraction. – Eljay Jul 24 '23 at 12:09
  • I think we can agree on that, I just provided an exaple which is not 0 cost abstraction. However, that doesn't answer at all my two questions. Why? What is the ranges version doing differently? Why can't the compiler optimize away the extra steps? – jjcasmar Jul 24 '23 at 12:22
  • 2
    This would be a great use case for a profiler. That would tell you exactly where each version is spending its time. – Stephen Newell Jul 24 '23 at 12:36

0 Answers0