Monthly Archives: Maj 2018

Czemu konkatenacja stringów jest wolniejsza niż użycie stringbuildera?

O tym że StringBuilder append jest dużo szybszy niż zwykła konkatenacja w języku C# wiedziałem, jednak nie miałem pojęcia jaka jest skala tych różnic i co za tym stoi. Nie zawsze mam czas na to żeby sprawdzać dlaczego coś działa tak a nie inaczej, ale tym razem miałem więc przygotowałem proste omówienie tego zjawiska 😉

String w języku C# (JAVA również) są niezmienne. Oznacza to, że metody działające na łańcuchach nie mogą nigdy zmienić wartości ciągu. Łączenie ciągów za pomocą += działa poprzez przydzielanie pamięci dla zupełnie nowego ciągu, który jest połączeniem dwóch poprzednich. Każda nowa konkatenacja wymaga zbudowania całkowicie nowego obiektu String a co za tym idzie zaalokować część pamięci w której będzie się nowy obiekt znajdował. To zajmuję czas i zwiększa użycie pamięci.

Z drugiej strony StringBuilder wstępnie alokuje bufor, a dodając do niego łańcuchy, nie trzeba go ponownie przypisywać (zakładając, że początkowy bufor jest wystarczająco duży). Co zwiększa wydajność i znacznie mniej obciąża pamięć.

Czy to oznacza że StringBuilder jest zawsze najlepszym rozwiązaniem? No właśnie nie zawsze, ponieważ w przypadku niedużych ciągów znaków ilość pamięci alokowanej i narzut wydajnościowy przewyższa proste użycie Stringa, a kod staje się nieco mniej czytelny niż proste wywołanie return string1 + string2;

Kod porównujący wydajność obu sposobów

public static void ZwyklaKonkatenacja()
{
	var tekst = "";
	Stopwatch test1 = Stopwatch.StartNew();
	test1.Start();
	for (int i = 0; i < 100000; i++)
	{
		tekst += "Y";
	}
	test1.Stop();
	Console.WriteLine("Konkatenacja " + test1.ElapsedMilliseconds + " ms");
}

public static void KonkatenacjaStringBuilder()
{
	var sb = new System.Text.StringBuilder();
	Stopwatch test2 = Stopwatch.StartNew();
	test2.Start();
	for (int i = 0; i < 100000; i++)
	{
		sb.Append("Y");
	}
	test2.Stop();
	Console.WriteLine("StringBuilder " + test2.ElapsedMilliseconds + " ms");
}

Wyniki szybkości działania funkcji

Wpis został zainspirowany przez kolegę z pracy, który ostatnio optymalizuje co tylko się da. Zaskoczył mnie, ponieważ wiedziałem że różnica jest, ale nie spodziewałem się że jest aż tak ogromna. Tak więc wielkie podziękowania.