Loading ...
Sorry, an error occurred while loading the content.

Otimização de código

Expand Messages
  • Adriano 'Stanley'
    Olá pessoal, bom dia. Há alguns dias venho estudando otimização de códigos em Java e têm surgido algumas dúvidas na implementação de métodos que
    Message 1 of 10 , Jun 28, 2011
    • 0 Attachment
      Olá pessoal, bom dia.

      Há alguns dias venho estudando otimização de códigos em Java e têm surgido algumas dúvidas na implementação de métodos que estão intactos desde o início do desenvolvimento do projeto e que são usados a todo tempo pela aplicação.

      Um desses métodos está em uma classe utilitária que usamos para converter Strings em inteiros.

      Li que um trecho circundado por try/catch tende a baixar a performance de um código e, realmente, o Profiler do Netbeans apontou como sendo o mais custoso de nossa classe de conversões gerais. Acontece que fazemos a conversão dessa forma:

      public static int converteInteiro(String a, int b) {
        try {
           return Integer.parseInt(a);
        } catch(Exception ex) {
           return b;
        }
      }

      A dúvida é, existe uma forma mais otimizada de se fazer isso? Todas as soluções que encontrei buscando em fóruns fazem uso do try/catch.

      Um grande abraço!

    • Romano Silva
      Você já fez o mesmo teste de profile com cenários para saber se o gargalo é o método parseInt ou o lançamento de Exceção? Ou seja, cenários onde nunca
      Message 2 of 10 , Jun 28, 2011
      • 0 Attachment
        Você já fez o mesmo teste de profile com cenários para saber se o gargalo é o método parseInt ou o lançamento de Exceção?

        Ou seja, cenários onde nunca é lançado exceção e cenários onde sempre é lançado exceção.

        Uma opção é alterar o método converteInteiro para fazer a mesma coisa que o parseInt faz só que sem lançar exceção. O código fonte do parseInt está disponível, basta copiar e onde estiver o código de lançar exceção, substitua por 'return b;'

        Você pode otimizar ainda o parseInt, substituindo o código onde ele recupera o digito da String por algo mais simples, assumindo que você está sempre usando base 10.

        Abraços,
        Romano Magacho

        2011/6/28 Adriano 'Stanley' <adrianostanley@...>
         

        Olá pessoal, bom dia.


        Há alguns dias venho estudando otimização de códigos em Java e têm surgido algumas dúvidas na implementação de métodos que estão intactos desde o início do desenvolvimento do projeto e que são usados a todo tempo pela aplicação.

        Um desses métodos está em uma classe utilitária que usamos para converter Strings em inteiros.

        Li que um trecho circundado por try/catch tende a baixar a performance de um código e, realmente, o Profiler do Netbeans apontou como sendo o mais custoso de nossa classe de conversões gerais. Acontece que fazemos a conversão dessa forma:

        public static int converteInteiro(String a, int b) {
          try {
             return Integer.parseInt(a);
          } catch(Exception ex) {
             return b;
          }
        }

        A dúvida é, existe uma forma mais otimizada de se fazer isso? Todas as soluções que encontrei buscando em fóruns fazem uso do try/catch.

        Um grande abraço!


      • Timothy High
        Otimização de desempenho é uma coisa engraçada, porque é mais fácil nos preocuparmos com nossas rotinas separadamente, sem pensar no contexto maior. Mas
        Message 3 of 10 , Jun 28, 2011
        • 0 Attachment
          Otimização de desempenho é uma coisa engraçada, porque é mais fácil nos preocuparmos com nossas rotinas separadamente, sem pensar no contexto maior. Mas geralmente com sistemas desenvolvidos em Java, o gargalo não está em uma rotina simples, e sim no algoritmo maior (e.g. está fazendo uma chamada remota ou no banco 1000 vezes quando poderia resolver com uma em batch). A dica é de não otimizar o sistema (e nem se preocupar com a otimização) até que estiver vendo um problema com o desempenho mesmo. E, então, otimizar apenas a parte que esteja causando o gargalo. Vide a página sobre otimização no Wikipedia (in inglês): http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize 

          Acho que, neste contexto, substituir uma rotina padrão do Java (parseInt) por uma rotina própria neste contexto seja radical demais, e provavelmente não resolveria o problema, se problema há. Se realmente está lançando exceção demais, minha dica seria fazer uma lavagem dos dados antes de chamar o parseInt. E.g. pode testar primeiro para "null" e retornar o b antes de chamá-lo. Se o problema não está nos parametros nulos, então tem que analisar porquê a sua aplicação está tentando converter tanto String que não é número em número. É porque o usuário pode passar qualquer valor no formulário? Neste caso, o problema está na falta de validação dos dados na UI. E etc.

          Fazer sua própria versão do parseInt também seria uma opção, mas só faria se o método for central da minha aplicação e realmente não existe controles sobre a formatação dos dados (e.g. um sistema de transformação de dados entre sistemas (EAI) que é executado 100.000 vezes por dia.

          abs,
          Tim.

          2011/6/28 Romano Silva <romano.magacho@...>
           

          Você já fez o mesmo teste de profile com cenários para saber se o gargalo é o método parseInt ou o lançamento de Exceção?

          Ou seja, cenários onde nunca é lançado exceção e cenários onde sempre é lançado exceção.

          Uma opção é alterar o método converteInteiro para fazer a mesma coisa que o parseInt faz só que sem lançar exceção. O código fonte do parseInt está disponível, basta copiar e onde estiver o código de lançar exceção, substitua por 'return b;'

          Você pode otimizar ainda o parseInt, substituindo o código onde ele recupera o digito da String por algo mais simples, assumindo que você está sempre usando base 10.

          Abraços,
          Romano Magacho



          2011/6/28 Adriano 'Stanley' <adrianostanley@...>
           

          Olá pessoal, bom dia.


          Há alguns dias venho estudando otimização de códigos em Java e têm surgido algumas dúvidas na implementação de métodos que estão intactos desde o início do desenvolvimento do projeto e que são usados a todo tempo pela aplicação.

          Um desses métodos está em uma classe utilitária que usamos para converter Strings em inteiros.

          Li que um trecho circundado por try/catch tende a baixar a performance de um código e, realmente, o Profiler do Netbeans apontou como sendo o mais custoso de nossa classe de conversões gerais. Acontece que fazemos a conversão dessa forma:

          public static int converteInteiro(String a, int b) {
            try {
               return Integer.parseInt(a);
            } catch(Exception ex) {
               return b;
            }
          }

          A dúvida é, existe uma forma mais otimizada de se fazer isso? Todas as soluções que encontrei buscando em fóruns fazem uso do try/catch.

          Um grande abraço!



        • Adriano 'Stanley'
          Entendi, mas acho que expliquei mal. O gargalo de toda aplicação não está neste método; quiz dizer que ele é o mais custoso da minha classe de
          Message 4 of 10 , Jun 28, 2011
          • 0 Attachment
            Entendi, mas acho que expliquei mal. O gargalo de toda aplicação não está neste método; quiz dizer que ele é o mais custoso da minha classe de conversão, somente, e nem há necessidade de otimizá-lo se for comparar com as outras classes/pacotes/camadas. Era mais uma curiosidade.

            Passando o Profiler na aplicação inteira tenho visto consultas utilizando Hibernate demorarem 100ms. Isso é um valor aceitável? Acredito que não, já que alguns refreshs na página inicial do sistema - somando o tempo dessas consultas - chega a 1250ms por cliente.
          • Felipe Fraga
            Concordo com o Timothy no que diz respeito a early optimization ser uma prática que deve ser aplicada com muita cautela. Diversos bons artigos existem na
            Message 5 of 10 , Jun 28, 2011
            • 0 Attachment
              Concordo com o Timothy no que diz respeito a early optimization ser uma prática que deve ser aplicada com muita cautela. Diversos bons artigos existem na internet sobre isso. Aumentar o hardware ou clusterizar a aplicação pode ser uma solução mais simples do que fazer diversas alterações de código.

              Quanto ao tempo de resposta ser aceitável, na minha opinião essa resposta não pode ser dada de maneira geral. Então o que acredito que precise ser feito é perguntar, se esse tempo de resposta é aceitável para o seu sistema.  Existem usuários humanos para ele? Quanto eles esperam de resposta? Quão crítico é a informação que eles estão esperando? 10 segundos de espera pode ser aceitável dependendo da situação, e estamos brigando por milisegundos.

              Novamente citando Fred Brooks: "There is no silver bullet".

              Abraços,

              Felipe Fraga


              2011/6/28 Adriano 'Stanley' <adrianostanley@...>
               

              Entendi, mas acho que expliquei mal. O gargalo de toda aplicação não está neste método; quiz dizer que ele é o mais custoso da minha classe de conversão, somente, e nem há necessidade de otimizá-lo se for comparar com as outras classes/pacotes/camadas. Era mais uma curiosidade.

              Passando o Profiler na aplicação inteira tenho visto consultas utilizando Hibernate demorarem 100ms. Isso é um valor aceitável? Acredito que não, já que alguns refreshs na página inicial do sistema - somando o tempo dessas consultas - chega a 1250ms por cliente.


            • Sigmar Siqueira
              Outra coisa que não foi mencionada, é que fazer micro-otimização no java não é tão simples assim. A implementação da jvm ( a da sun por exemplo )
              Message 6 of 10 , Jun 28, 2011
              • 0 Attachment
                Outra coisa que não foi mencionada, é que fazer micro-otimização no java não é tão simples assim.

                A implementação da jvm ( a da sun por exemplo ) tenta fazer diversas otimizações na execução do  pseudo-código. E sua otimização no java pode até atrapalhar a otimização da JVM.

                O que li num artigo na sun, que não estou encontrando agora, é que se preocupe menos com essas otimizações e se preocupe mais em desenvolver código orientado a objeto, que é o código esperado pela JVM e que ela busca otimizar.

                Quanto ao hibernate não entendi o que são os 100ms. 
                Existem 2 aspectos que eu acho importante. Um é o tempo de execução da API do hibernate. Criação dos objetos, preparação da consulta etc... e outro o tempo de execução da consulta no Servidor de Banco.

                Pra otimizar é preciso separar os dois e ver quanto tempo a consulta(ou consultas) SQL que o hibernate está fazendo leva. E depois ver se dá pra otimizar, mudando o mapeamento pra gerar consultas mais rápidas no servidor, por exemplo,  coisas do como remover um join que não precisa, ou usar como filtro um campo com indice na tabela no banco.
                O google tem muita coisa sobre isso.

                Abraços,

                Sigmar

                Em 28 de junho de 2011 11:54, Felipe Fraga <felipefraga@...> escreveu:
                 

                Concordo com o Timothy no que diz respeito a early optimization ser uma prática que deve ser aplicada com muita cautela. Diversos bons artigos existem na internet sobre isso. Aumentar o hardware ou clusterizar a aplicação pode ser uma solução mais simples do que fazer diversas alterações de código.

                Quanto ao tempo de resposta ser aceitável, na minha opinião essa resposta não pode ser dada de maneira geral. Então o que acredito que precise ser feito é perguntar, se esse tempo de resposta é aceitável para o seu sistema.  Existem usuários humanos para ele? Quanto eles esperam de resposta? Quão crítico é a informação que eles estão esperando? 10 segundos de espera pode ser aceitável dependendo da situação, e estamos brigando por milisegundos.

                Novamente citando Fred Brooks: "There is no silver bullet".

                Abraços,

                Felipe Fraga


                2011/6/28 Adriano 'Stanley' <adrianostanley@...>
                 

                Entendi, mas acho que expliquei mal. O gargalo de toda aplicação não está neste método; quiz dizer que ele é o mais custoso da minha classe de conversão, somente, e nem há necessidade de otimizá-lo se for comparar com as outras classes/pacotes/camadas. Era mais uma curiosidade.

                Passando o Profiler na aplicação inteira tenho visto consultas utilizando Hibernate demorarem 100ms. Isso é um valor aceitável? Acredito que não, já que alguns refreshs na página inicial do sistema - somando o tempo dessas consultas - chega a 1250ms por cliente.





                --
                Sigmar Siqueira

              • Adriano 'Stanley'
                Esse lance de nem sempre a otimização reduzir o tempo é verdade. Passando pelo código encontrei um método que concatenava strings com + . Ao trocar por
                Message 7 of 10 , Jun 30, 2011
                • 0 Attachment
                  Esse lance de nem sempre a otimização reduzir o tempo é verdade. Passando pelo código encontrei um método que concatenava strings com "+". Ao trocar por String.format ou StringBuilder, curiosamente o código ficou mais lento - claro, em questão de milisegundos.

                  Agradeço a todos pelas opiniões e pela participação no tópico.

                  Abraço!
                • Eldio Santos Jr.
                  Uma outra questão a se levantar (apesar de parecer óbvio para alguns) é quanto tempo você ficou analisando o desempenho? A tendência é de a cada
                  Message 8 of 10 , Jun 30, 2011
                  • 0 Attachment
                    Uma outra questão a se levantar (apesar de parecer óbvio para alguns) é quanto tempo você ficou analisando o desempenho? A tendência é de a cada repetição do código ele baixar o consumo (processamento) até um limite, claro. E quanto ao Hibernate (não tenho certeza) acredito que nas primeiras consultas ele seja realmente mais lento por estar criando o cache, que ele usa para reduzir o tempo de resposta em consultas, o que depois de um tempo também costuma reduzir.

                    ________________
                    Eldio Santos Junior
                    Tel.: (21) 8884-3757
                    Skype: eldiojr
                    Twitter: @eldius


                    Em 30 de junho de 2011 07:20, Adriano 'Stanley' <adrianostanley@...> escreveu:
                     

                    Esse lance de nem sempre a otimização reduzir o tempo é verdade. Passando pelo código encontrei um método que concatenava strings com "+". Ao trocar por String.format ou StringBuilder, curiosamente o código ficou mais lento - claro, em questão de milisegundos.


                    Agradeço a todos pelas opiniões e pela participação no tópico.

                    Abraço!


                  • Felipe Fraga
                    Melhorar o desempenho gradativamente a cada execução eu não entendi bem, você poderia por favor explicar melhor? Eu entendo no caso do cache do hibernate,
                    Message 9 of 10 , Jun 30, 2011
                    • 0 Attachment
                      Melhorar o desempenho gradativamente a cada execução eu não entendi bem, você poderia por favor explicar melhor? Eu entendo no caso do cache do hibernate, mas em execuções gerais de programas não.

                      Uma coisa que a JVM faz é JIT, ou seja, ela compila trechos de código que são repetidos muitas vezes para o processador nativo em  tempo de execução. No momento que a VM decide por isso, esse trecho de código passa a ser executado mais rapidamente.

                      Abraço

                      Felipe Fraga


                      2011/6/30 Eldio Santos Jr. <eldiosantos@...>
                       

                      Uma outra questão a se levantar (apesar de parecer óbvio para alguns) é quanto tempo você ficou analisando o desempenho? A tendência é de a cada repetição do código ele baixar o consumo (processamento) até um limite, claro. E quanto ao Hibernate (não tenho certeza) acredito que nas primeiras consultas ele seja realmente mais lento por estar criando o cache, que ele usa para reduzir o tempo de resposta em consultas, o que depois de um tempo também costuma reduzir.

                      ________________
                      Eldio Santos Junior
                      Tel.: (21) 8884-3757
                      Skype: eldiojr
                      Twitter: @eldius




                      Em 30 de junho de 2011 07:20, Adriano 'Stanley' <adrianostanley@...> escreveu:

                       

                      Esse lance de nem sempre a otimização reduzir o tempo é verdade. Passando pelo código encontrei um método que concatenava strings com "+". Ao trocar por String.format ou StringBuilder, curiosamente o código ficou mais lento - claro, em questão de milisegundos.


                      Agradeço a todos pelas opiniões e pela participação no tópico.

                      Abraço!



                    • Eldio Santos Jr.
                      A questão é mais ou menos essa... Porém se você for analisar um pouco mais a fundo, nem sempre há apenas uma forma de executar as coisas (inclusive em se
                      Message 10 of 10 , Jun 30, 2011
                      • 0 Attachment
                        A questão é mais ou menos essa... Porém se você for analisar um pouco mais a fundo, nem sempre há apenas uma forma de executar as coisas (inclusive em se falando de instruções binárias), e o que o JIT tende a fazer é analisar este trecho que é executado muitas vezes e compilar de forma a otimizar para as situações em que ele é mais executado... Por isso a tendência é ele melhorar (como disse, até um certo limite) de acordo com os dados de execução...

                        Seguem 2 links que talvez te ajudem a entender melhor:


                        http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html

                        ________________
                        Eldio Santos Junior
                        Tel.: (21) 8884-3757
                        Skype: eldiojr
                        Twitter: @eldius


                        Em 30 de junho de 2011 17:23, Felipe Fraga <felipefraga@...> escreveu:
                         

                        Melhorar o desempenho gradativamente a cada execução eu não entendi bem, você poderia por favor explicar melhor? Eu entendo no caso do cache do hibernate, mas em execuções gerais de programas não.

                        Uma coisa que a JVM faz é JIT, ou seja, ela compila trechos de código que são repetidos muitas vezes para o processador nativo em  tempo de execução. No momento que a VM decide por isso, esse trecho de código passa a ser executado mais rapidamente.

                        Abraço

                        Felipe Fraga


                        2011/6/30 Eldio Santos Jr. <eldiosantos@...>

                         

                        Uma outra questão a se levantar (apesar de parecer óbvio para alguns) é quanto tempo você ficou analisando o desempenho? A tendência é de a cada repetição do código ele baixar o consumo (processamento) até um limite, claro. E quanto ao Hibernate (não tenho certeza) acredito que nas primeiras consultas ele seja realmente mais lento por estar criando o cache, que ele usa para reduzir o tempo de resposta em consultas, o que depois de um tempo também costuma reduzir.

                        ________________
                        Eldio Santos Junior
                        Tel.: (21) 8884-3757
                        Skype: eldiojr
                        Twitter: @eldius




                        Em 30 de junho de 2011 07:20, Adriano 'Stanley' <adrianostanley@...> escreveu:

                         

                        Esse lance de nem sempre a otimização reduzir o tempo é verdade. Passando pelo código encontrei um método que concatenava strings com "+". Ao trocar por String.format ou StringBuilder, curiosamente o código ficou mais lento - claro, em questão de milisegundos.


                        Agradeço a todos pelas opiniões e pela participação no tópico.

                        Abraço!




                      Your message has been successfully submitted and would be delivered to recipients shortly.