StringBuilder question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jerry

    StringBuilder question

    Assuming we've defined StringBuilder myBuilder, which of the following is most expensive:

    //scenario 1
    myBuilder.Appen d("test" + "test" + "test");

    //scenario 2
    myBuilder.Appen d("test");
    myBuilder.Appen d("test");
    myBuilder.Appen d("test");
  • Shakir Hussain

    #2
    Re: StringBuilder question

    Jerry,

    you mean more number of lines as expensive? or the performance?

    I would say the correct way to do that may be

    myBuilder.Appen d("test").Appen d("test1").Appe nd("test2");

    Shak.


    "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
    news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...[color=blue]
    > Assuming we've defined StringBuilder myBuilder, which of the following is[/color]
    most expensive:[color=blue]
    >
    > //scenario 1
    > myBuilder.Appen d("test" + "test" + "test");
    >
    > //scenario 2
    > myBuilder.Appen d("test");
    > myBuilder.Appen d("test");
    > myBuilder.Appen d("test");[/color]


    Comment

    • John Wood

      #3
      Re: StringBuilder question

      scenario 1, because a new copy of the string is being created for each +
      operation (which is why there is a StringBuilder class in the first place).

      However, it's possible (because of constant folding) that may actually
      compile to be myBuilding.Appe nd("testtesttes t");, in which case the second
      scenario would be more expensive.

      --
      John Wood
      EMail: first name, dot, last name, at priorganize.com

      "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
      news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...[color=blue]
      > Assuming we've defined StringBuilder myBuilder, which of the following is[/color]
      most expensive:[color=blue]
      >
      > //scenario 1
      > myBuilder.Appen d("test" + "test" + "test");
      >
      > //scenario 2
      > myBuilder.Appen d("test");
      > myBuilder.Appen d("test");
      > myBuilder.Appen d("test");[/color]


      Comment

      • Daniel Billingsley

        #4
        Re: StringBuilder question

        And of course, both are more expensive than

        someString = "test" + "test" + "test";

        in both lines of code and performance.

        "John Wood" <j@ro.com> wrote in message
        news:eyuv3kVWEH A.2928@tk2msftn gp13.phx.gbl...[color=blue]
        > scenario 1, because a new copy of the string is being created for each +
        > operation (which is why there is a StringBuilder class in the first[/color]
        place).[color=blue]
        >
        > However, it's possible (because of constant folding) that may actually
        > compile to be myBuilding.Appe nd("testtesttes t");, in which case the second
        > scenario would be more expensive.
        >
        > --
        > John Wood
        > EMail: first name, dot, last name, at priorganize.com
        >
        > "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
        > news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...[color=green]
        > > Assuming we've defined StringBuilder myBuilder, which of the following[/color][/color]
        is[color=blue]
        > most expensive:[color=green]
        > >
        > > //scenario 1
        > > myBuilder.Appen d("test" + "test" + "test");
        > >
        > > //scenario 2
        > > myBuilder.Appen d("test");
        > > myBuilder.Appen d("test");
        > > myBuilder.Appen d("test");[/color]
        >
        >[/color]


        Comment

        • John Wood

          #5
          Re: StringBuilder question

          Right. If it does implement constant folding for literal strings that may
          just become an assignment of the interned string "testtestte st" (which will
          just be a object handle) to a string reference variable... like 1 IL
          instruction.

          --
          John Wood
          EMail: first name, dot, last name, at priorganize.com
          "Daniel Billingsley" <dbillingsley@N O_durcon_SPAAMM .com> wrote in message
          news:%23yQCUwVW EHA.1764@TK2MSF TNGP10.phx.gbl. ..[color=blue]
          > And of course, both are more expensive than
          >
          > someString = "test" + "test" + "test";
          >
          > in both lines of code and performance.
          >
          > "John Wood" <j@ro.com> wrote in message
          > news:eyuv3kVWEH A.2928@tk2msftn gp13.phx.gbl...[color=green]
          > > scenario 1, because a new copy of the string is being created for each +
          > > operation (which is why there is a StringBuilder class in the first[/color]
          > place).[color=green]
          > >
          > > However, it's possible (because of constant folding) that may actually
          > > compile to be myBuilding.Appe nd("testtesttes t");, in which case the[/color][/color]
          second[color=blue][color=green]
          > > scenario would be more expensive.
          > >
          > > --
          > > John Wood
          > > EMail: first name, dot, last name, at priorganize.com
          > >
          > > "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
          > > news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...[color=darkred]
          > > > Assuming we've defined StringBuilder myBuilder, which of the following[/color][/color]
          > is[color=green]
          > > most expensive:[color=darkred]
          > > >
          > > > //scenario 1
          > > > myBuilder.Appen d("test" + "test" + "test");
          > > >
          > > > //scenario 2
          > > > myBuilder.Appen d("test");
          > > > myBuilder.Appen d("test");
          > > > myBuilder.Appen d("test");[/color]
          > >
          > >[/color]
          >
          >[/color]


          Comment

          • Jerry

            #6
            Re: StringBuilder question

            RE: And of course, both are more expensive than someString = "test" + "test" + "test"

            Let's change this scenario. Pretend there is a string variable named example. Now, which is more expensive in terms of performance & memory alloc.

            //scenario 1
            myBuilder.Appen d("test" + example + "test");

            //scenario 2
            myBuilder.Appen d("test");
            myBuilder.Appen d(example);
            myBuilder.Appen d("test");

            //scenario 3
            string myString = "test" + example + "test";


            Jerry

            "John Wood" wrote:
            [color=blue]
            > Right. If it does implement constant folding for literal strings that may
            > just become an assignment of the interned string "testtestte st" (which will
            > just be a object handle) to a string reference variable... like 1 IL
            > instruction.
            >
            > --
            > John Wood
            > EMail: first name, dot, last name, at priorganize.com
            > "Daniel Billingsley" <dbillingsley@N O_durcon_SPAAMM .com> wrote in message
            > news:%23yQCUwVW EHA.1764@TK2MSF TNGP10.phx.gbl. ..[color=green]
            > > And of course, both are more expensive than
            > >
            > > someString = "test" + "test" + "test";
            > >
            > > in both lines of code and performance.
            > >
            > > "John Wood" <j@ro.com> wrote in message
            > > news:eyuv3kVWEH A.2928@tk2msftn gp13.phx.gbl...[color=darkred]
            > > > scenario 1, because a new copy of the string is being created for each +
            > > > operation (which is why there is a StringBuilder class in the first[/color]
            > > place).[color=darkred]
            > > >
            > > > However, it's possible (because of constant folding) that may actually
            > > > compile to be myBuilding.Appe nd("testtesttes t");, in which case the[/color][/color]
            > second[color=green][color=darkred]
            > > > scenario would be more expensive.
            > > >
            > > > --
            > > > John Wood
            > > > EMail: first name, dot, last name, at priorganize.com
            > > >
            > > > "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
            > > > news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...
            > > > > Assuming we've defined StringBuilder myBuilder, which of the following[/color]
            > > is[color=darkred]
            > > > most expensive:
            > > > >
            > > > > //scenario 1
            > > > > myBuilder.Appen d("test" + "test" + "test");
            > > > >
            > > > > //scenario 2
            > > > > myBuilder.Appen d("test");
            > > > > myBuilder.Appen d("test");
            > > > > myBuilder.Appen d("test");
            > > >
            > > >[/color]
            > >
            > >[/color]
            >
            >
            >[/color]

            Comment

            • John Wood

              #7
              Re: StringBuilder question

              scenario1 probably more expensive because of the memory copying that's going
              on.

              Depending on the size of the string in 'example', scenario2 would probably
              be the fastest.

              --
              John Wood
              EMail: first name, dot, last name, at priorganize.com

              "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
              news:4A110FA8-27CE-48EF-95B4-5FE4AE12F788@mi crosoft.com...[color=blue]
              > RE: And of course, both are more expensive than someString = "test" +[/color]
              "test" + "test"[color=blue]
              >
              > Let's change this scenario. Pretend there is a string variable named[/color]
              example. Now, which is more expensive in terms of performance & memory
              alloc.[color=blue]
              >
              > //scenario 1
              > myBuilder.Appen d("test" + example + "test");
              >
              > //scenario 2
              > myBuilder.Appen d("test");
              > myBuilder.Appen d(example);
              > myBuilder.Appen d("test");
              >
              > //scenario 3
              > string myString = "test" + example + "test";
              >
              >
              > Jerry
              >
              > "John Wood" wrote:
              >[color=green]
              > > Right. If it does implement constant folding for literal strings that[/color][/color]
              may[color=blue][color=green]
              > > just become an assignment of the interned string "testtestte st" (which[/color][/color]
              will[color=blue][color=green]
              > > just be a object handle) to a string reference variable... like 1 IL
              > > instruction.
              > >
              > > --
              > > John Wood
              > > EMail: first name, dot, last name, at priorganize.com
              > > "Daniel Billingsley" <dbillingsley@N O_durcon_SPAAMM .com> wrote in[/color][/color]
              message[color=blue][color=green]
              > > news:%23yQCUwVW EHA.1764@TK2MSF TNGP10.phx.gbl. ..[color=darkred]
              > > > And of course, both are more expensive than
              > > >
              > > > someString = "test" + "test" + "test";
              > > >
              > > > in both lines of code and performance.
              > > >
              > > > "John Wood" <j@ro.com> wrote in message
              > > > news:eyuv3kVWEH A.2928@tk2msftn gp13.phx.gbl...
              > > > > scenario 1, because a new copy of the string is being created for[/color][/color][/color]
              each +[color=blue][color=green][color=darkred]
              > > > > operation (which is why there is a StringBuilder class in the first
              > > > place).
              > > > >
              > > > > However, it's possible (because of constant folding) that may[/color][/color][/color]
              actually[color=blue][color=green][color=darkred]
              > > > > compile to be myBuilding.Appe nd("testtesttes t");, in which case the[/color]
              > > second[color=darkred]
              > > > > scenario would be more expensive.
              > > > >
              > > > > --
              > > > > John Wood
              > > > > EMail: first name, dot, last name, at priorganize.com
              > > > >
              > > > > "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
              > > > > news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...
              > > > > > Assuming we've defined StringBuilder myBuilder, which of the[/color][/color][/color]
              following[color=blue][color=green][color=darkred]
              > > > is
              > > > > most expensive:
              > > > > >
              > > > > > //scenario 1
              > > > > > myBuilder.Appen d("test" + "test" + "test");
              > > > > >
              > > > > > //scenario 2
              > > > > > myBuilder.Appen d("test");
              > > > > > myBuilder.Appen d("test");
              > > > > > myBuilder.Appen d("test");
              > > > >
              > > > >
              > > >
              > > >[/color]
              > >
              > >
              > >[/color][/color]


              Comment

              • Jon Skeet [C# MVP]

                #8
                Re: StringBuilder question

                Jerry <Jerry@discussi ons.microsoft.c om> wrote:[color=blue]
                > RE: And of course, both are more expensive than someString = "test" + "test" + "test"
                >
                > Let's change this scenario. Pretend there is a string variable named
                > example. Now, which is more expensive in terms of performance &
                > memory alloc.
                >
                > //scenario 1
                > myBuilder.Appen d("test" + example + "test");
                >
                > //scenario 2
                > myBuilder.Appen d("test");
                > myBuilder.Appen d(example);
                > myBuilder.Appen d("test");
                >
                > //scenario 3
                > string myString = "test" + example + "test";[/color]

                Scenario 3 is the cheapest: it involves a single call to String.Concat,
                which is able to work out the total length of the string, allocate the
                appropriate memory, and then copy the 3 strings in place.

                --
                Jon Skeet - <skeet@pobox.co m>
                Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                If replying to the group, please do not mail me too

                Comment

                • J.Marsch

                  #9
                  Re: StringBuilder question

                  According to Rico Mariani (MS performance guru), it depends. It sounds like
                  something like:
                  someString = "test" + "test" + "test";
                  only counts as one concatenation, so it's not really worth a StringBuilder.

                  Some interesting info here:


                  and here:




                  "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
                  news:4A110FA8-27CE-48EF-95B4-5FE4AE12F788@mi crosoft.com...[color=blue]
                  > RE: And of course, both are more expensive than someString = "test" +[/color]
                  "test" + "test"[color=blue]
                  >
                  > Let's change this scenario. Pretend there is a string variable named[/color]
                  example. Now, which is more expensive in terms of performance & memory
                  alloc.[color=blue]
                  >
                  > //scenario 1
                  > myBuilder.Appen d("test" + example + "test");
                  >
                  > //scenario 2
                  > myBuilder.Appen d("test");
                  > myBuilder.Appen d(example);
                  > myBuilder.Appen d("test");
                  >
                  > //scenario 3
                  > string myString = "test" + example + "test";
                  >
                  >
                  > Jerry
                  >
                  > "John Wood" wrote:
                  >[color=green]
                  > > Right. If it does implement constant folding for literal strings that[/color][/color]
                  may[color=blue][color=green]
                  > > just become an assignment of the interned string "testtestte st" (which[/color][/color]
                  will[color=blue][color=green]
                  > > just be a object handle) to a string reference variable... like 1 IL
                  > > instruction.
                  > >
                  > > --
                  > > John Wood
                  > > EMail: first name, dot, last name, at priorganize.com
                  > > "Daniel Billingsley" <dbillingsley@N O_durcon_SPAAMM .com> wrote in[/color][/color]
                  message[color=blue][color=green]
                  > > news:%23yQCUwVW EHA.1764@TK2MSF TNGP10.phx.gbl. ..[color=darkred]
                  > > > And of course, both are more expensive than
                  > > >
                  > > > someString = "test" + "test" + "test";
                  > > >
                  > > > in both lines of code and performance.
                  > > >
                  > > > "John Wood" <j@ro.com> wrote in message
                  > > > news:eyuv3kVWEH A.2928@tk2msftn gp13.phx.gbl...
                  > > > > scenario 1, because a new copy of the string is being created for[/color][/color][/color]
                  each +[color=blue][color=green][color=darkred]
                  > > > > operation (which is why there is a StringBuilder class in the first
                  > > > place).
                  > > > >
                  > > > > However, it's possible (because of constant folding) that may[/color][/color][/color]
                  actually[color=blue][color=green][color=darkred]
                  > > > > compile to be myBuilding.Appe nd("testtesttes t");, in which case the[/color]
                  > > second[color=darkred]
                  > > > > scenario would be more expensive.
                  > > > >
                  > > > > --
                  > > > > John Wood
                  > > > > EMail: first name, dot, last name, at priorganize.com
                  > > > >
                  > > > > "Jerry" <Jerry@discussi ons.microsoft.c om> wrote in message
                  > > > > news:24BF3B72-7A07-492F-A0CD-9561CBA4A289@mi crosoft.com...
                  > > > > > Assuming we've defined StringBuilder myBuilder, which of the[/color][/color][/color]
                  following[color=blue][color=green][color=darkred]
                  > > > is
                  > > > > most expensive:
                  > > > > >
                  > > > > > //scenario 1
                  > > > > > myBuilder.Appen d("test" + "test" + "test");
                  > > > > >
                  > > > > > //scenario 2
                  > > > > > myBuilder.Appen d("test");
                  > > > > > myBuilder.Appen d("test");
                  > > > > > myBuilder.Appen d("test");
                  > > > >
                  > > > >
                  > > >
                  > > >[/color]
                  > >
                  > >
                  > >[/color][/color]


                  Comment

                  • Jerry

                    #10
                    Re: StringBuilder question

                    So what the hey is StringBuilder for? Can someone provide an example where using StringBuilder will be less expensive than an approach using string concatenation?

                    "Jon Skeet [C# MVP]" wrote:
                    [color=blue]
                    > Jerry <Jerry@discussi ons.microsoft.c om> wrote:[color=green]
                    > > RE: And of course, both are more expensive than someString = "test" + "test" + "test"
                    > >
                    > > Let's change this scenario. Pretend there is a string variable named
                    > > example. Now, which is more expensive in terms of performance &
                    > > memory alloc.
                    > >
                    > > //scenario 1
                    > > myBuilder.Appen d("test" + example + "test");
                    > >
                    > > //scenario 2
                    > > myBuilder.Appen d("test");
                    > > myBuilder.Appen d(example);
                    > > myBuilder.Appen d("test");
                    > >
                    > > //scenario 3
                    > > string myString = "test" + example + "test";[/color]
                    >
                    > Scenario 3 is the cheapest: it involves a single call to String.Concat,
                    > which is able to work out the total length of the string, allocate the
                    > appropriate memory, and then copy the 3 strings in place.
                    >
                    > --
                    > Jon Skeet - <skeet@pobox.co m>
                    > http://www.pobox.com/~skeet
                    > If replying to the group, please do not mail me too
                    >[/color]

                    Comment

                    • Daniel Billingsley

                      #11
                      Re: StringBuilder question

                      Yep, the third is still faster. Even doing it like
                      string myString = "test";
                      myString += example;
                      myString += "test";

                      it would still be faster than the corresponding StringBuilder (if you
                      include the required .ToString() ) in this specific example.

                      Keep in mind, even though this is a pet topic of mine, that we're talking
                      microseconds of difference for a single call so it's almost always better to
                      just write the code that looks the cleanest. I would consider that to be #3
                      in your specific example, but with a bit more complexity of the strings
                      being concatenated I would use string.Format() for that reason, even though
                      it is considerably slower than all these alternatives.

                      "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                      news:MPG.1b43f9 0dd7d3106d98ad7 c@msnews.micros oft.com...[color=blue]
                      > Jerry <Jerry@discussi ons.microsoft.c om> wrote:[color=green]
                      > > RE: And of course, both are more expensive than someString = "test" +[/color][/color]
                      "test" + "test"[color=blue][color=green]
                      > >
                      > > Let's change this scenario. Pretend there is a string variable named
                      > > example. Now, which is more expensive in terms of performance &
                      > > memory alloc.
                      > >
                      > > //scenario 1
                      > > myBuilder.Appen d("test" + example + "test");
                      > >
                      > > //scenario 2
                      > > myBuilder.Appen d("test");
                      > > myBuilder.Appen d(example);
                      > > myBuilder.Appen d("test");
                      > >
                      > > //scenario 3
                      > > string myString = "test" + example + "test";[/color]
                      >
                      > Scenario 3 is the cheapest: it involves a single call to String.Concat,
                      > which is able to work out the total length of the string, allocate the
                      > appropriate memory, and then copy the 3 strings in place.
                      >
                      > --
                      > Jon Skeet - <skeet@pobox.co m>
                      > http://www.pobox.com/~skeet
                      > If replying to the group, please do not mail me too[/color]


                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: StringBuilder question

                        Jerry <Jerry@discussi ons.microsoft.c om> wrote:[color=blue]
                        > So what the hey is StringBuilder for? Can someone provide an example
                        > where using StringBuilder will be less expensive than an approach
                        > using string concatenation?[/color]

                        Sure - any time you don't have all the information in some static way
                        to start with. For instance:

                        StringBuilder builder = new StringBuilder() ;
                        using (StreamReader reader = ...)
                        {
                        string line;
                        while ( (line=reader.Re adLine()) != null)
                        {
                        string word = ProcessLineSome how();
                        builder.Append( word);
                        }
                        }

                        --
                        Jon Skeet - <skeet@pobox.co m>
                        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                        If replying to the group, please do not mail me too

                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: StringBuilder question

                          J.Marsch <jeremy@ctcdeve loper.com> wrote:[color=blue]
                          > According to Rico Mariani (MS performance guru), it depends. It sounds like
                          > something like:
                          > someString = "test" + "test" + "test";
                          > only counts as one concatenation, so it's not really worth a StringBuilder.
                          >
                          > Some interesting info here:
                          > http://weblogs.asp.net/ricom/archive.../02/40778.aspx
                          >
                          > and here:
                          > http://weblogs.asp.net/ricom/archive.../15/43628.aspx[/color]

                          While I haven't been able to find where it's documented, I believe the
                          above actually doesn't count as *any* concatenations - it compiles to
                          the same code as

                          someString = "testtestte st";

                          --
                          Jon Skeet - <skeet@pobox.co m>
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                          If replying to the group, please do not mail me too

                          Comment

                          • John Wood

                            #14
                            Re: StringBuilder question

                            I just tested this... it does. (compiles to ldstr "testtestte st")
                            Plus I saw constant folding listed as one of the JIT's optimization
                            features.

                            --
                            John Wood
                            EMail: first name, dot, last name, at priorganize.com
                            "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                            news:MPG.1b4401 60136d578698ad7 e@msnews.micros oft.com...[color=blue]
                            > J.Marsch <jeremy@ctcdeve loper.com> wrote:[color=green]
                            > > According to Rico Mariani (MS performance guru), it depends. It sounds[/color][/color]
                            like[color=blue][color=green]
                            > > something like:
                            > > someString = "test" + "test" + "test";
                            > > only counts as one concatenation, so it's not really worth a[/color][/color]
                            StringBuilder.[color=blue][color=green]
                            > >
                            > > Some interesting info here:
                            > > http://weblogs.asp.net/ricom/archive.../02/40778.aspx
                            > >
                            > > and here:
                            > > http://weblogs.asp.net/ricom/archive.../15/43628.aspx[/color]
                            >
                            > While I haven't been able to find where it's documented, I believe the
                            > above actually doesn't count as *any* concatenations - it compiles to
                            > the same code as
                            >
                            > someString = "testtestte st";
                            >
                            > --
                            > Jon Skeet - <skeet@pobox.co m>
                            > http://www.pobox.com/~skeet
                            > If replying to the group, please do not mail me too[/color]


                            Comment

                            • John Wood

                              #15
                              Re: StringBuilder question

                              It's also worth noting that Concat has the following overloads:

                              string, string
                              string, string, string
                              string, string, string, string
                              string[]

                              So if your expression has more than four +s... it'll do quite a bit more
                              work (constructing an array and putting each item into the array before
                              calling).

                              Although this is probably still considerably less work than what
                              stringbuilder would do.

                              --
                              John Wood
                              EMail: first name, dot, last name, at priorganize.com
                              "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
                              news:MPG.1b4401 60136d578698ad7 e@msnews.micros oft.com...[color=blue]
                              > J.Marsch <jeremy@ctcdeve loper.com> wrote:[color=green]
                              > > According to Rico Mariani (MS performance guru), it depends. It sounds[/color][/color]
                              like[color=blue][color=green]
                              > > something like:
                              > > someString = "test" + "test" + "test";
                              > > only counts as one concatenation, so it's not really worth a[/color][/color]
                              StringBuilder.[color=blue][color=green]
                              > >
                              > > Some interesting info here:
                              > > http://weblogs.asp.net/ricom/archive.../02/40778.aspx
                              > >
                              > > and here:
                              > > http://weblogs.asp.net/ricom/archive.../15/43628.aspx[/color]
                              >
                              > While I haven't been able to find where it's documented, I believe the
                              > above actually doesn't count as *any* concatenations - it compiles to
                              > the same code as
                              >
                              > someString = "testtestte st";
                              >
                              > --
                              > Jon Skeet - <skeet@pobox.co m>
                              > http://www.pobox.com/~skeet
                              > If replying to the group, please do not mail me too[/color]


                              Comment

                              Working...