Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is simple but frequent usage of std::stringstream a premature pessimization?

I have a simple scenario. I need to join two C-strings together into a std::string. I have decided to do this in one of two ways:

Solution 1

void ProcessEvent(char const* pName) {
   std::string fullName;
   fullName.reserve(50); // Ensure minimal reallocations for small event names (50 is an arbitrary limit).
   fullName += "com.domain.events.";
   fullName += pName;

   // Use fullName as needed
}

Solution 2

void ProcessEvent(char const* pName) {
   std::ostringstream ss;
   ss << "com.domain.events." << pName;

   std::string fullName{ss.str()};
   // Use fullName as needed
}

I like solution 2 better because the code is more natural. Solution 1 seems like a response to a measurable bottleneck from performance testing. However, Solution 1 exists for 2 reasons:

  1. It's a light optimization to reduce allocations. Event management in this application is used quite frequently so there might be benefits (but no measurements have been taken).
  2. I've heard criticism regarding STL streams WRT performance. Some have recommended to only use stringstream when doing heavy string building, especially those involving number conversions and/or usage of manipulators.

Is it a premature pessimization to prefer solution 2 for its simplicity? Or is it a premature optimization to choose solution 1? I'm wondering if I'm too overly concerned about STL streams.

like image 854
void.pointer Avatar asked Oct 20 '14 20:10

void.pointer


1 Answers

Let's measure it

A quick test with the following functions:

void func1(const char* text) {
    std::string s;
    s.reserve(50);
    s += "com.domain.event.";
    s += text;
}

void func2(const char* text) {
    std::ostringstream oss;
    oss << "com.domain.event." << text;
    std::string s = oss.str();
}

Running each 100 000 times in a loop gives the following results on average on my computer (using gcc-4.9.1):

func1 : 37 milliseconds

func2 : 87 milliseconds

That is, func1 is more than twice as fast.

That being said, I would recommend using the clearest most readable syntax until you really need the performance. Implement a testable program first, then optimize if its too slow.

Edit:

As suggested by @Ken P:

void func3(const char* text) {
    std::string s = "com.domain.event" + std::string{text};
}

func3 : 27 milliseconds

The simplest solution is often the fastest.

like image 185
Felix Glas Avatar answered Oct 19 '22 05:10

Felix Glas