Avoid String in a loop

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Avoid String in a loop

Otávio Gonçalves de Santana
The reason to prefer StringBuilder is that both + and concat create a new
object every time you call them (provided the right-hand side argument is
not empty). This can quickly add up to a lot of objects, almost all of
which are completely unnecessary.

public class Main{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " +
(System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " +
(System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}


   - slow elapsed 11741 ms
   - fast elapsed 7 ms

Also, this PR avoids unnecessary call in StringBuilder
Ref: https://github.com/apache/tomee/pull/219
Reply | Threaded
Open this post in threaded view
|

Re: Avoid String in a loop

Daniel Cunha-2
Wowww!

Nice catch Otávio!
That is really a good improvement!

Em seg, 26 de nov de 2018 às 10:47, Otávio Gonçalves de Santana <
[hidden email]> escreveu:

> The reason to prefer StringBuilder is that both + and concat create a new
> object every time you call them (provided the right-hand side argument is
> not empty). This can quickly add up to a lot of objects, almost all of
> which are completely unnecessary.
>
> public class Main{
>     public static void main(String[] args)
>     {
>         long now = System.currentTimeMillis();
>         slow();
>         System.out.println("slow elapsed " +
> (System.currentTimeMillis() - now) + " ms");
>
>         now = System.currentTimeMillis();
>         fast();
>         System.out.println("fast elapsed " +
> (System.currentTimeMillis() - now) + " ms");
>     }
>
>     private static void fast()
>     {
>         StringBuilder s = new StringBuilder();
>         for(int i=0;i<100000;i++)
>             s.append("*");
>     }
>
>     private static void slow()
>     {
>         String s = "";
>         for(int i=0;i<100000;i++)
>             s+="*";
>     }
> }
>
>
>    - slow elapsed 11741 ms
>    - fast elapsed 7 ms
>
> Also, this PR avoids unnecessary call in StringBuilder
> Ref: https://github.com/apache/tomee/pull/219
>


--
Daniel "soro" Cunha
https://twitter.com/dvlc_
Reply | Threaded
Open this post in threaded view
|

Re: Avoid String in a loop

Romain Manni-Bucau
+0 (this is only for error cases as far as i saw and a few concatenations
so you don't see the diff in practise + the compiler is able to optimize it
and even replace string builder when relevant these days)

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 26 nov. 2018 à 15:38, Daniel Cunha <[hidden email]> a écrit :

> Wowww!
>
> Nice catch Otávio!
> That is really a good improvement!
>
> Em seg, 26 de nov de 2018 às 10:47, Otávio Gonçalves de Santana <
> [hidden email]> escreveu:
>
> > The reason to prefer StringBuilder is that both + and concat create a new
> > object every time you call them (provided the right-hand side argument is
> > not empty). This can quickly add up to a lot of objects, almost all of
> > which are completely unnecessary.
> >
> > public class Main{
> >     public static void main(String[] args)
> >     {
> >         long now = System.currentTimeMillis();
> >         slow();
> >         System.out.println("slow elapsed " +
> > (System.currentTimeMillis() - now) + " ms");
> >
> >         now = System.currentTimeMillis();
> >         fast();
> >         System.out.println("fast elapsed " +
> > (System.currentTimeMillis() - now) + " ms");
> >     }
> >
> >     private static void fast()
> >     {
> >         StringBuilder s = new StringBuilder();
> >         for(int i=0;i<100000;i++)
> >             s.append("*");
> >     }
> >
> >     private static void slow()
> >     {
> >         String s = "";
> >         for(int i=0;i<100000;i++)
> >             s+="*";
> >     }
> > }
> >
> >
> >    - slow elapsed 11741 ms
> >    - fast elapsed 7 ms
> >
> > Also, this PR avoids unnecessary call in StringBuilder
> > Ref: https://github.com/apache/tomee/pull/219
> >
>
>
> --
> Daniel "soro" Cunha
> https://twitter.com/dvlc_
>
Reply | Threaded
Open this post in threaded view
|

Re: Avoid String in a loop

jgallimore
I was surprised the figures were as different as they are. I appreciate
Romain's feedback - I suspect we won't see dramatic performance increases,
but it certainly doesn't do us any harm, so I'll merge this in. Thanks for
the patch!

Jon

On Mon, Nov 26, 2018 at 2:40 PM Romain Manni-Bucau <[hidden email]>
wrote:

> +0 (this is only for error cases as far as i saw and a few concatenations
> so you don't see the diff in practise + the compiler is able to optimize it
> and even replace string builder when relevant these days)
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <
> https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <
> https://www.packtpub.com/application-development/java-ee-8-high-performance
> >
>
>
> Le lun. 26 nov. 2018 à 15:38, Daniel Cunha <[hidden email]> a
> écrit :
>
> > Wowww!
> >
> > Nice catch Otávio!
> > That is really a good improvement!
> >
> > Em seg, 26 de nov de 2018 às 10:47, Otávio Gonçalves de Santana <
> > [hidden email]> escreveu:
> >
> > > The reason to prefer StringBuilder is that both + and concat create a
> new
> > > object every time you call them (provided the right-hand side argument
> is
> > > not empty). This can quickly add up to a lot of objects, almost all of
> > > which are completely unnecessary.
> > >
> > > public class Main{
> > >     public static void main(String[] args)
> > >     {
> > >         long now = System.currentTimeMillis();
> > >         slow();
> > >         System.out.println("slow elapsed " +
> > > (System.currentTimeMillis() - now) + " ms");
> > >
> > >         now = System.currentTimeMillis();
> > >         fast();
> > >         System.out.println("fast elapsed " +
> > > (System.currentTimeMillis() - now) + " ms");
> > >     }
> > >
> > >     private static void fast()
> > >     {
> > >         StringBuilder s = new StringBuilder();
> > >         for(int i=0;i<100000;i++)
> > >             s.append("*");
> > >     }
> > >
> > >     private static void slow()
> > >     {
> > >         String s = "";
> > >         for(int i=0;i<100000;i++)
> > >             s+="*";
> > >     }
> > > }
> > >
> > >
> > >    - slow elapsed 11741 ms
> > >    - fast elapsed 7 ms
> > >
> > > Also, this PR avoids unnecessary call in StringBuilder
> > > Ref: https://github.com/apache/tomee/pull/219
> > >
> >
> >
> > --
> > Daniel "soro" Cunha
> > https://twitter.com/dvlc_
> >
>