1. #1
    Albireo's Avatar
    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);
    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);
            }
        }
    (voor het geval iemand nog moest twijfelen aan het nut van StringBuilder)
    no votes  

  2. #2

    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  

  3. #3
    ArnoDF's Avatar
    Registered
    04/06/05
    Location
    grimbergen
    Posts
    272
    iTrader
    0
    Mentioned
    0 Post(s)
    Reputation
    0/0
    wel leuke PoC
    handtekening: krabbel krabbel
    no votes  

  4. #4
    Da Turtle's Avatar
    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 Java
    no votes  

  5. #5
    Albireo's Avatar
    Registered
    21/10/05
    Location
    Herentals
    Posts
    1,515
    iTrader
    5 (100%)
    Mentioned
    0 Post(s)
    Reputation
    2/13
    Quote Originally Posted by Da Turtle View Post
    This quote is hidden because you are ignoring this member. Show
    Ik denk dat het ook wel duidelijk ging zijn met 10 000 chars, dan moet je geen 16 minuten wachten .
    982591ms / 54ms (1 000 000) is veel indrukwekkender dan 42ms / 1ms (10 000)
    no votes  

  6. #6
    Bubbling Zombie's Avatar
    Registered
    03/11/03
    Location
    Hove
    Posts
    6,718
    iTrader
    3 (100%)
    Mentioned
    0 Post(s)
    Reputation
    1/3
    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 yourself
    no votes  

  7. #7

    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 :

    Code:
    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);
                }
            }
        }
    }
    Hiervoor heb ik dit benchmark programma gebruikt: http://www.yoda.arachsys.com/csharp/benchmark.html

    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  

  8. #8
    UniKorn's Avatar
    Registered
    20/09/02
    Location
    Leuven
    Posts
    460
    iTrader
    0
    Mentioned
    0 Post(s)
    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  

  9. #9
    Emerxill's Avatar
    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 civilization
    no votes  

  10. #10
    Ice's Avatar
    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  

  11. #11
    Emerxill's Avatar
    Registered
    17/07/02
    Location
    Hasselt
    Posts
    2,970
    iTrader
    0
    Mentioned
    0 Post(s)
    Reputation
    0/18
    Quote Originally Posted by Ice View Post
    This quote is hidden because you are ignoring this member. Show
    String is immutable dus duh @ UniKorn & duh @ Emerxill
    Sorry voor het vermelden uwe alwetendheid
    If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization
    no votes  

  12. #12
    Bubbling Zombie's Avatar
    Registered
    03/11/03
    Location
    Hove
    Posts
    6,718
    iTrader
    3 (100%)
    Mentioned
    0 Post(s)
    Reputation
    1/3
    Quote Originally Posted by Emerxill View Post
    This quote is hidden because you are ignoring this member. Show
    Sorry voor het vermelden uwe alwetendheid
    Als ge da als "weetje van den dag" aanpakt is el Iceman wel alwetend ja :|
    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 yourself
    no votes  

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

Log in

Log in