String performance in C++?

Started by
25 comments, last by chairthrower 15 years, 9 months ago
Hi everyone I was considering performance of std::string and CString class in MFC and so far I came up with an idea that string performance could be improved. ( I'm not 100% sure so pls correct me if I'm wrong :) ) - When string operation is performed, there exists many temporary objects and each allocates (and soon deallocate) a buffer from heap. (Am I right?) - If that's the case, wouldn't it possible to enhance string performance by implementing a specific heap for temporary storage? I've got the idea of temporary-specific heap from here ((Chapter 2 "And in theory ...")::("2) Garbage collection ...")::(3rd paragraph, "with GC, ...")). Though I don't totally agree with that article, I think it might be profitable for temporary storage. So, would it enhance performance of string operation? and if it does, will it be worth? Or is there already solution for temporary-specific heap? Thanks in advance
Advertisement
Yes, this might enhance the performance of string manipulation a small bit, if it involved a large number of medium-sized strings being manipulated. However, detecting temporary strings is the actual difficulty1mdash;in most cases, building strings using a string-builder pattern (such as an ostringstream) takes as much effort and has a better result because it reduces the number of temporaries.
Quote:Original post by 1hod0afop

- When string operation is performed, there exists many temporary objects and each allocates (and soon deallocate) a buffer from heap. (Am I right?)


This will depend on operations performed.

Quote: - If that's the case, wouldn't it possible to enhance string performance by implementing a specific heap for temporary storage?


Not for general case. If you find a specific scenario however, using custom allocators, provided by all STL containers may help. Improvements noted are up to a factor of 50.

Quote:will it be worth?


Depends on how you use these strings.
Writing custom allocators for strings is something you only really need to do as a last resort optimisation.
In my experience, std:string performs pretty well. The only optimizations I could found in my string class were to use memcpy instead of strcpy and implement CoW (although if you are careful when writing code, you don't really need it).
2+2=5, for big values of 2!
Thanks for replies.

In-place allocators are incredibly fast, yeah. But it has very restricted usage since it can't free blocks individually. The allocator probably doesn't know if requested memory is for temporary or relatively permanent. The goal in GC heap is its "relocatability". i.e. memory blocks can be moved from place to place behind the scene. Because of that the heap can remain compacted and thus allowing fast allocation like in-place allocators. Moving heap frame behind the scene is very dangerous in C++ and will require a great care. I couldn't find way to implement relocatable allocator in STL (without ENORMOUS overhead).
Probably the GC heap will also have restricted usage. I don't think it's possible to allocate objects in GC heap without compiler's support.

Quote:Original post by Antheus
Improvements noted are up to a factor of 50.

The fact that in-place allocator can be 50x faster encouraged me a lot. I'm gonna start CRAZY battle again, with GC heap (more precisely "relocatable heap")

Regards
Quote:Original post by 1hod0afop
- When string operation is performed, there exists many temporary objects and each allocates (and soon deallocate) a buffer from heap. (Am I right?)

Give an example of your supposed usage. It's probably abusive.

std::string a, b, c, d, e; // assume these are all initialized
std::string r(a + b + c + d + e); // this will construct a bunch of temporaries and copy (and re-copy) 7 or 8 times

The code above is a typical case of abusing std::string. "But then," you ask, "how is one supposed to concatenate many strings?!"

C++ has a mostly overlooked tool for doing just that called std::stringstream.

std::string a, b, c, d, e; // assume these are all initialized
std::ostringstream ss;
ss << a << b << c << d << e; // best case this will copy all the strings into a suitably-sized buffer. worst case it'll need to resize a couple times, but should always invoke fewer copies than the code above
std::string r(ss.str());

Granted a specialized heap for these allocation operations would be beneficial, but is not needed if your initial buffer is large enough that you never have to resize and thus allocate again. If you simply copy the strings from the source buffers to the destination then you've already achieved maximum performance.
Ra
Quote:Original post by Ra
Give an example of your supposed usage. It's probably abusive.

I'm highly negative of using std::string. On my computer just concatenating 2 std::string's each 10 characters-long takes 0.9 microseconds! (don't think I'm using 10-year-old or such antique machine) If I instead use strcpy/strcat it takes only 50 nanoseconds. That's why I never use std::string. Now the reason why I'm doing this is to allow such abuse of strings. Actually the guys behind me are using std::string now also. They're making me crazy. Analyzing their code, find such abuses, optimizing ... It's time to end this crazy course.

[Edited by - 1hod0afop on July 11, 2008 2:10:47 AM]
Quote:Original post by 1hod0afop
Quote:Original post by Ra
Give an example of your supposed usage. It's probably abusive.

I'm highly negative of using std::string. On my computer just concatenating 2 std::string's each 10 characters-long takes 0.9 miliseconds! (don't think I'm using 10-year-old or such antique machine) If I instead use strcpy/strcat it takes only 50 nanoseconds. That's why I never use std::string. Now the reason why I'm doing this is to allow such abuse of strings. Actually the guys behind me are using std::string now also. They're making me crazy. Analyzing their code, find such abuses, optimizing ... It's time to end this crazy course.


Are you sure that you are not profiling in debug mode? That seems like a huge time difference.
Quote:Original post by EasilyConfused
Are you sure that you are not profiling in debug mode? That seems like a huge time difference.


OK here's a simple program
#include <windows.h>#include <stdio.h>#include <string>void main(){	unsigned int uStart = GetTickCount();	std::string str1 = "0123456789";	std::string str2 = "abcdefghij";	for( int i = 0; i < 1000000; i ++ )		std::string concat = str1 + str2;	unsigned int uElapsed = GetTickCount() - uStart;	printf( "%d ns\n", uElapsed );}


In Visual Studio 2005, it outputs
Debug build : 3015 ns
Release build : 860 ns

However, by linking CRT library static it gets a little faster
Release build /MT : 657 ns

This topic is closed to new replies.

Advertisement