-
28-09-2007, 01:12 #1Member
- Registered
- 21/10/05
- Location
- Herentals
- Posts
- 1,515
- iTrader
- 5 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 2/13
[PROG][.NET] Illustratie waarom StringBuilder een goed idee is
Ik was in m'n design patterns boek code tegengekomen om te timen hoelang een methode erover doet om afgehandeld te worden en die wou ik eens uitproberen. En omdat ze altijd zeggen om StringBuilder te gebruiken i.p.v. string als je veel bewerkingen op die string moet uitvoeren heb ik eens getest hoelang het duurt om 1 000 000 char's aan mekaar te plakken; 1 keer met StringBuilder.Append en 1 keer met String+=
resultaat
- via String: 982591ms (16 minuten)
- via StringBuilder: 54ms
Code:RandomWordCreator creator = new RandomWordCreator(); creator.Length = 1000000; Console.WriteLine(ShowTimerCommand.TimeThis(new Command(creator.Create)).TotalMilliseconds); Console.WriteLine(ShowTimerCommand.TimeThis(new Command(creator.CreateString)).TotalMilliseconds);(voor het geval iemand nog moest twijfelen aan het nut van StringBuilder)Code:public class RandomWordCreator { private static readonly char[] charset=new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; private string randomword; private int length; public int Length { set { this.length = value; } } public string RandomWord { get { return this.randomword; } } public void Create() { this.randomword=CreateRandomWord(this.length); } public void CreateString() { this.randomword = CreateRandomString(this.length); } public static string CreateRandomWord(int length) { StringBuilder sb = new StringBuilder(length); Random rnd=new Random(); for (int i = 0; i < length; i++) { sb.Append(RandomWordCreator.charset[rnd.Next(26)]); } return sb.ToString(); } public static string CreateRandomString(int length) { string sb=""; Random rnd = new Random(); for (int i = 0; i < length; i++) { sb+=(RandomWordCreator.charset[rnd.Next(26)]); } return sb; } } public delegate void Command(); public class ShowTimerCommand { public static void Snooze() { System.Threading.Thread.Sleep(2000); } public static TimeSpan TimeThis(Command c) { DateTime t1 = DateTime.Now; c.Invoke(); return DateTime.Now.Subtract(t1); } }no votes
-
-
28-09-2007, 13:21 #2Member
- Registered
- 12/10/02
- Location
- mars
- Posts
- 14,319
- iTrader
- 2 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
Ehm, iedereen die 2 seconden de achtergrond opzoekt weet dit hoor
.
Simpele reden is dat StringBuilder een buffer bijhoudt en deze desnoods verlengt. String zelf is statisch, elke keer je de string wijzigt (append, remove, ...) wordt uw huidige string verwijderd en een nieuwe aangemaakt
(en dan heb je nog temp vars en zo).
Last edited by killgore; 28-09-2007 at 18:29.
no votes
-
28-09-2007, 17:22 #3Approved 9-lifer
- Registered
- 04/06/05
- Location
- grimbergen
- Posts
- 272
- iTrader
- 0
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
wel leuke PoC
handtekening: krabbel krabbelno votes
-
28-09-2007, 21:22 #4Member
- Registered
- 22/10/02
- Location
- Brugge & Gent
- Posts
- 657
- iTrader
- 0
- Mentioned
- 0 Post(s)
- Reputation
- 0/1
Ik denk dat het ook wel duidelijk ging zijn met 10 000 chars, dan moet je geen 16 minuten wachten
.
//edit: Ik dacht even aan Javano votes
-
28-09-2007, 21:42 #5Member
- Registered
- 21/10/05
- Location
- Herentals
- Posts
- 1,515
- iTrader
- 5 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 2/13
no votes
-
29-09-2007, 21:36 #6Member
- Registered
- 03/11/03
- Location
- Hove
- Posts
- 6,718
- iTrader
- 3 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 1/3
Doe uw research is wa deftig.
http://www.chinhdo.com/chinh/blog/20...uilder-part-2/Look down at me and you see a fool; look up at me and you see a god; look straight at me and you see yourselfno votes
-
30-09-2007, 12:34 #7Member
- Registered
- 12/10/02
- Location
- mars
- Posts
- 14,319
- iTrader
- 2 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
ook niet echt een logische benchmark he.
Bij de stringbuilder gaan ze 3 keer appenden en gebruiken ze empty constructor
bij de string gaan ze 2x gaan appenden en gebruiken ze de string init constructor. Dat is sowieso al een operatie minder die je bij stringbuilder ook kan gaan doen
.
Dat zijn benchmarks die afhangen van slechte/goede code, zo kan ik ook gaan bewijzen dat php 10x sneller is als pure assembler.
edit: een 2e reden is dat je hier opeenvolgende code hebt die de compiler in geval 2 (de string) naar 1 statement zal herleiden:
string s = i.ToString() + i.ToString() + i.ToString();
iets dat ook veel makkellijker te optimaliseren is & maar 1x geheugen (re)allocatie vraagt, iets dat bij de stringbuilder ook niet snel zal gebeuren. Een vrij onrealistische situatie imho.
edit: het is wel wat sneller heb ik gemerkt, maar met iets logischere codes die ik gebruikte werd het verschil echt minimaal
:
Hiervoor heb ik dit benchmark programma gebruikt: http://www.yoda.arachsys.com/csharp/benchmark.htmlCode:using System.Text; using System; namespace test { class Program { static int loops = 1000000; [Benchmark] public static void TestBuilder1() { for (int i = 0; i <= loops; i++) { StringBuilder s = new StringBuilder(); s.Append(i.ToString()); s.Append(i.ToString()); s.Append(i.ToString()); } } [Benchmark] public static void TestString1() { for (int i = 0; i <= loops; i++) { string s = i.ToString(); s = s + i.ToString(); s = s + i.ToString(); } } [Benchmark] public static void TestBuilder2() { for (int i = 0; i <= loops; i++) { StringBuilder s = new StringBuilder(i.ToString()); s.Append(i.ToString()); s.Append(i.ToString()); } } [Benchmark] public static void TestBuilder3() { for (int i = 0; i <= loops; i++) { StringBuilder s = new StringBuilder(i.ToString()); s.Append(s); s.Append(s); } } [Benchmark] public static void TestString3() { for (int i = 0; i <= loops; i++) { string s = i.ToString(); s += s; s += s; } } [Benchmark] public static void TestBuilder4() { for (int i = 0; i <= loops; i++) { String tmp = i.ToString(); StringBuilder s = new StringBuilder(tmp); s.Append(tmp).Append(tmp); } } } }
het verschil tussen TestString3 en TestBuilder4 is iets van 0,01 seconde op zovele loops
. En ik blijf het een onrealistische situatie vinden, je zal hier veeleer formatters voor gaan gebruiken dan appends. Ik denk dat in elke "normale" append situatie builder sneller zal zijn.
Last edited by killgore; 30-09-2007 at 13:54.
no votes
-
07-10-2007, 22:50 #8
Een ander verschil tussen beiden is dat bij
+= ipv een stringbuilder er 2x geheugen ingepakt wordt.Uzghul, 70 Rogue; Tankghul, 70 Warrior; Uziuz, 70 Paladin; Skinny, 70 Priest; Darkrune, 70 Warlock; UniKorn, 60 Druid; Martinuz, 59 Hunter; Marceluz, 59 Mage; Flexy, 30 Rogue;no votes
-
10-10-2007, 14:04 #9Member
- Registered
- 17/07/02
- Location
- Hasselt
- Posts
- 2,970
- iTrader
- 0
- Mentioned
- 0 Post(s)
- Reputation
- 0/18
Conclusie: gebruik StringBuffer als ge bewerkingen wil doen op de tekst.
Als er geen bewerkingen nodig zijn, gebruik dan String.If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilizationno votes
-
10-10-2007, 14:30 #10Member
- Registered
- 31/07/02
- Location
- Kontich
- Posts
- 602
- iTrader
- 16 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
String is immutable dus duh @ UniKorn & duh @ Emerxill
When you're slapped, you'll take it and like it - Sam Spade
Make way for the bad guy! - Tony Montana
When a girl has a heart of stone, there's only one way to melt it. Just add Ice.
no votes
-
10-10-2007, 18:18 #11Member
- Registered
- 17/07/02
- Location
- Hasselt
- Posts
- 2,970
- iTrader
- 0
- Mentioned
- 0 Post(s)
- Reputation
- 0/18
no votes
-
10-10-2007, 18:54 #12Member
- Registered
- 03/11/03
- Location
- Hove
- Posts
- 6,718
- iTrader
- 3 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 1/3
no votes

