Pergunta: O tratamento de exceções em Java é realmente lento?
A sabedoria convencional, assim como muitos resultados do Google, diz que uma lógica excepcional não deve ser usada para o fluxo normal de programas em Java. Duas razões são geralmente apresentadas,
- é realmente lento - até uma ordem de magnitude mais lenta que o código normal (os motivos apresentados variam),
e
- é confuso porque as pessoas esperam que apenas erros sejam tratados em código excepcional.
Esta pergunta é sobre # 1.
Como exemplo, esta página descreve o tratamento de exceções Java como "muito lento" e relaciona a lentidão à criação da sequência de mensagens de exceção - "essa sequência é usada na criação do objeto de exceção que é lançado. Isso não é rápido". O artigo Tratamento efetivo de exceções em Java diz que "o motivo disso é devido ao aspecto de criação de objeto do tratamento de exceções, o que torna o lançamento de exceções inerentemente lento". Outro motivo é que a geração de rastreamento de pilha é o que a torna mais lenta.
Meu teste (usando Java 1.6.0_07, Java HotSpot 10.0, no Linux de 32 bits) indica que o tratamento de exceções não é mais lento que o código normal. Tentei executar um método em um loop que executa algum código. No final do método, eu uso um booleano para indicar se deve retornar ou lançar . Dessa forma, o processamento real é o mesmo. Tentei executar os métodos em diferentes ordens e calcular a média dos meus tempos de teste, pensando que poderia ter sido o aquecimento da JVM. Em todos os meus testes, o arremesso foi pelo menos tão rápido quanto o retorno, se não mais rápido (até 3,1% mais rápido). Estou completamente aberto à possibilidade de meus testes estarem errados, mas não vi nada por aí no caminho do exemplo de código, comparações de testes ou resultados nos últimos dois anos que mostram que o tratamento de exceções em Java é realmente lento.
O que me levou a seguir esse caminho foi uma API que eu precisava usar que gerou exceções como parte da lógica de controle normal. Eu queria corrigi-los em seu uso, mas agora talvez não consiga. Em vez disso, terei que elogiá-los por sua visão de futuro?
No artigo Manuseio eficiente de exceções Java na compilação just-in-time , os autores sugerem que a presença de manipuladores de exceção, mesmo que nenhuma exceção seja lançada, é suficiente para impedir que o compilador JIT otimize o código corretamente, diminuindo a velocidade dele . Ainda não testei essa teoria.
fonte
exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow
- dando uma explicação completa e extensa sobre o porquê. E ele foi o cara que escreveu a Java lib. Portanto, ele é quem define o contrato de API das classes. Eu concordo com Bill K neste.Respostas:
Depende de como as exceções são implementadas. A maneira mais simples é usar setjmp e longjmp. Isso significa que todos os registros da CPU são gravados na pilha (o que já leva algum tempo) e possivelmente outros dados precisam ser criados ... tudo isso já acontece na instrução try. A instrução throw precisa desenrolar a pilha e restaurar os valores de todos os registros (e possíveis outros valores na VM). Portanto, try e throw são igualmente lentos, e isso é bastante lento, no entanto, se nenhuma exceção é lançada, sair do bloco try não leva tempo na maioria dos casos (como tudo é colocado na pilha que limpa automaticamente se o método existir).
A Sun e outros reconheceram que isso é possivelmente subótimo e, é claro, as VMs ficam cada vez mais rápidas ao longo do tempo. Existe outra maneira de implementar exceções, o que faz com que a tentativa se torne muito rápida (na verdade, nada acontece para tentar em geral - tudo o que precisa acontecer já está feito quando a classe é carregada pela VM) e torna o lançamento não tão lento . Não sei qual JVM usa essa técnica nova e melhor ...
... mas você está escrevendo em Java para que seu código posteriormente seja executado apenas em uma JVM em um sistema específico? Desde que, se alguma vez for executado em qualquer outra plataforma ou qualquer outra versão da JVM (possivelmente de qualquer outro fornecedor), quem disse que eles também usam a implementação rápida? O mais rápido é mais complicado que o mais lento e não é facilmente possível em todos os sistemas. Você quer ficar portátil? Então não confie nas exceções que são rápidas.
Também faz uma grande diferença o que você faz dentro de um bloco try. Se você abrir um bloco try e nunca chamar nenhum método dentro desse bloco try, o bloco try será ultra rápido, pois o JIT pode realmente tratar um arremesso como um simples goto. Ele não precisa salvar o estado da pilha nem precisa desenrolar a pilha se uma exceção for lançada (ela só precisará pular para os manipuladores de captura). No entanto, isso não é o que você costuma fazer. Normalmente, você abre um bloco try e, em seguida, chama um método que pode gerar uma exceção, certo? E mesmo se você apenas usar o bloco try dentro do seu método, que tipo de método será esse que não chama outro método? Apenas calculará um número? Então, para que você precisa de exceções? Existem maneiras muito mais elegantes de regular o fluxo do programa. Para praticamente qualquer outra coisa, exceto matemática simples,
Veja o seguinte código de teste:
Resultado:
A desaceleração do bloco try é muito pequena para excluir fatores de confusão, como processos em segundo plano. Mas o bloco de captura matou tudo e tornou 66 vezes mais lento!
Como eu disse, o resultado não será tão ruim se você colocar try / catch e throw tudo dentro do mesmo método (método3), mas esta é uma otimização JIT especial em que eu não confiaria. E mesmo ao usar essa otimização, o arremesso ainda é bem lento. Portanto, não sei o que você está tentando fazer aqui, mas há definitivamente uma maneira melhor de fazê-lo do que usar try / catch / throw.
fonte
nanoTime()
requer o Java 1.5 e eu só tinha o Java 1.4 disponível no sistema que usei para escrever o código acima. Também não desempenha um papel importante na prática. A única diferença entre os dois é que um é nanossegundo e outro milissegundos enanoTime
não é influenciado por manipulações de relógio (que são irrelevantes, a menos que você ou o processo do sistema modifique o relógio do sistema exatamente no momento em que o código de teste está sendo executado). Geralmente você está certo, porém,nanoTime
é obviamente a melhor escolha.try
bloco, mas nãothrow
. Seuthrow
teste está lançando exceções 50% das vezes que passa pelotry
. Essa é claramente uma situação em que a falha não é excepcional . Reduzir isso para apenas 10% reduz massivamente o impacto no desempenho. O problema com esse tipo de teste é que ele encoraja as pessoas a parar de usar as exceções completamente. O uso de exceções, para tratamento excepcional de casos, tem um desempenho muito melhor do que o que mostra seu teste.return
. Ele deixa um método em algum lugar no meio do corpo, talvez até no meio de uma operação (que até agora foi concluída em apenas 50%) e ocatch
bloco pode ter 20 quadros de pilha para cima (um método tem umtry
bloco, chamando method1, que chama method2, que chama mehtod3, ... e no method20, no meio de uma operação, uma exceção é lançada). A pilha deve girar 20 quadros para cima, todas as operações inacabadas devem ser desfeitas (as operações não devem ter sido concluídas pela metade) e os registros da CPU precisam estar em um estado limpo. Tudo isso consome tempo.Para sua informação, estendi o experimento que Mecki fez:
Os três primeiros são iguais aos do Mecki (meu laptop é obviamente mais lento).
method4 é idêntico ao method3, exceto pelo fato de criar um em
new Integer(1)
vez de fazerthrow new Exception()
.method5 é como method3, exceto que ele cria o
new Exception()
sem lançá-lo.method6 é como method3, exceto que lança uma exceção pré-criada (uma variável de instância) em vez de criar uma nova.
Em Java, grande parte da despesa de lançar uma exceção é o tempo gasto na coleta do rastreamento de pilha, que ocorre quando o objeto de exceção é criado. O custo real de lançar a exceção, embora grande, é consideravelmente menor que o custo de criar a exceção.
fonte
Aleksey Shipilëv fez uma análise muito minuciosa na qual ele avalia as exceções de Java sob várias combinações de condições:
Ele também os compara ao desempenho de verificar um código de erro em vários níveis de frequência de erro.
As conclusões (citadas literalmente em seu post) foram:
Exceções verdadeiramente excepcionais têm um ótimo desempenho. Se você usá-los como projetado, e apenas comunicar casos verdadeiramente excepcionais entre o número esmagadoramente grande de casos não excepcionais tratados por código regular, o uso de exceções é a conquista do desempenho.
Os custos de desempenho das exceções têm dois componentes principais: construção do rastreio da pilha quando a exceção é instanciada e desenrolamento da pilha durante o lançamento da exceção.
Os custos de construção do rastreamento de pilha são proporcionais à profundidade da pilha no momento da instanciação da exceção. Isso já é ruim, porque quem sabe a profundidade da pilha na qual esse método de lançamento seria chamado? Mesmo se você desativar a geração de rastreamento de pilha e / ou armazenar em cache as exceções, você poderá se livrar dessa parte do custo de desempenho.
Os custos de desenrolamento da pilha dependem da sorte que temos em aproximar o manipulador de exceções no código compilado. Estruturar cuidadosamente o código para evitar a pesquisa profunda de manipuladores de exceção provavelmente está nos ajudando a ter mais sorte.
Se eliminarmos ambos os efeitos, o custo de desempenho das exceções é o da filial local. Não importa o quão bonito seja, isso não significa que você deve usar Exceções como o fluxo de controle usual, porque nesse caso você está à mercê de otimizar o compilador! Você deve usá-los apenas em casos verdadeiramente excepcionais, nos quais a frequência da exceção amortiza o possível custo infeliz de aumentar a exceção real.
A regra geral otimista parece ter uma frequência de 10 ^ -4, pois as exceções são suficientemente excepcionais. Isso, é claro, depende dos pesos pesados das próprias exceções, das ações exatas tomadas nos manipuladores de exceções, etc.
O resultado é que, quando uma exceção não é lançada, você não paga um custo; portanto, quando a condição excepcional é suficientemente rara, o tratamento de exceções é mais rápido do que o uso
if
sempre. O post completo vale muito a pena ser lido.fonte
Infelizmente, minha resposta é muito longa para postar aqui. Então, deixe-me resumir aqui e encaminhá-lo para http://www.fuwjax.com/how-slow-are-java-exceptions/ para obter os detalhes mais detalhados.
A verdadeira questão aqui não é "Quão lenta são as 'falhas relatadas como exceções' em comparação com o 'código que nunca falha'?" como a resposta aceita pode fazer você acreditar. Em vez disso, a pergunta deve ser "Quão lenta são as 'falhas relatadas como exceções' em comparação com as falhas relatadas de outras maneiras?" Geralmente, as duas outras formas de relatar falhas são com valores de sentinela ou com wrappers de resultados.
Os valores do Sentinel são uma tentativa de retornar uma classe no caso de sucesso e outra no caso de falha. Você pode pensar nisso quase como retornar uma exceção em vez de lançar uma. Isso requer uma classe pai compartilhada com o objeto de sucesso e, em seguida, faz uma verificação de "instanceof" e um par lança para obter as informações de sucesso ou falha.
Acontece que, com o risco de segurança do tipo, os valores do Sentinel são mais rápidos que as exceções, mas apenas por um fator de aproximadamente 2x. Agora, isso pode parecer muito, mas 2x apenas cobre o custo da diferença de implementação. Na prática, o fator é muito menor, pois nossos métodos que podem falhar são muito mais interessantes do que alguns operadores aritméticos, como no código de exemplo em outras partes desta página.
Os Wrappers de resultado, por outro lado, não sacrificam a segurança do tipo. Eles agrupam as informações de sucesso e falha em uma única classe. Portanto, em vez de "instanceof", eles fornecem um "isSuccess ()" e getters para os objetos de sucesso e falha. No entanto, os objetos de resultado são aproximadamente duas vezes mais lentos do que usando exceções. Acontece que criar um novo objeto wrapper toda vez é muito mais caro do que lançar uma exceção às vezes.
Além disso, as exceções são o idioma fornecido para indicar que um método pode falhar. Não há outra maneira de dizer apenas pela API quais métodos devem sempre (principalmente) funcionar e quais devem reportar falhas.
As exceções são mais seguras que os sentinelas, mais rápidas que os objetos resultantes e menos surpreendentes que qualquer uma delas. Não estou sugerindo que try / catch substitua if / else, mas as exceções são a maneira correta de relatar falhas, mesmo na lógica comercial.
Dito isso, gostaria de salientar que as duas formas mais freqüentes de impactar substancialmente o desempenho que encontrei estão criando objetos desnecessários e loops aninhados. Se você tiver uma escolha entre criar uma exceção ou não, não crie a exceção. Se você tiver a opção entre criar uma exceção às vezes ou criar outro objeto o tempo todo, crie a exceção.
fonte
Estendi as respostas dadas por @Mecki e @incarnate , sem o preenchimento de stacktrace para Java.
Com o Java 7+, podemos usar
Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)
. Mas para Java6, veja minha resposta para esta perguntaSaída com Java 1.6.0_45, no Core i7, 8 GB de RAM:
Portanto, os métodos still que retornam valores são mais rápidos, em comparação com os métodos que lançam exceções. IMHO, não podemos projetar uma API clara usando apenas tipos de retorno para fluxos de sucesso e erro. Os métodos que lançam exceções sem rastreamento de pilha são 4-5 vezes mais rápidos que as exceções normais.
Edit: NoStackTraceThrowable.java Obrigado @Greg
fonte
public class NoStackTraceThrowable extends Throwable { public NoStackTraceThrowable() { super("my special throwable", null, false, false); } }
With Java 7+, we can use
mas depois você escreveu,Output with Java 1.6.0_45,
então esse é o resultado do Java 6 ou 7?Throwable
construtor que possuiboolean writableStackTrace
arg. Mas isso não está presente no Java 6 e abaixo. É por isso que dei implementação personalizada para Java 6 e abaixo. Portanto, o código acima é para Java 6 e abaixo. Por favor, leia a primeira linha do segundo parágrafo com cuidado.Optional
ou similar chegou um pouco tarde para o Java. Antes disso, também usamos objetos wrapper com sinalizadores de sucesso / erro. Mas parece ser um pouco hacks e não me parece natural.Há um tempo atrás, escrevi uma classe para testar o desempenho relativo da conversão de strings em ints usando duas abordagens: (1) chame Integer.parseInt () e capture a exceção, ou (2) combine a string com um regex e chame parseInt () somente se a partida for bem-sucedida. Usei a regex da maneira mais eficiente possível (por exemplo, criando os objetos Pattern e Matcher antes de inserir o loop) e não imprimi nem salvei os traços de pilha das exceções.
Para uma lista de dez mil strings, se todos fossem números válidos, a abordagem parseInt () era quatro vezes mais rápida que a abordagem regex. Mas se apenas 80% das seqüências de caracteres fossem válidas, o regex seria duas vezes mais rápido que parseInt (). E se 20% eram válidos, significando que a exceção era lançada e capturada 80% das vezes, o regex era cerca de vinte vezes mais rápido que parseInt ().
Fiquei surpreso com o resultado, considerando que a abordagem regex processa seqüências de caracteres válidas duas vezes: uma para a correspondência e outra para parseInt (). Mas lançar e capturar exceções mais do que compensava isso. É provável que esse tipo de situação não ocorra com muita frequência no mundo real, mas, se ocorrer, você definitivamente não deve usar a técnica de captura de exceções. Mas se você estiver validando apenas a entrada do usuário ou algo assim, use a abordagem parseInt ().
fonte
Integer.ParseInt()
) e espero que, na maioria das vezes, a entrada do usuário esteja correta, portanto, para o meu caso de uso, parece que tomar o hit de exceção ocasional é o caminho a percorrer .Acho que o primeiro artigo se refere ao ato de percorrer a pilha de chamadas e criar um rastreamento de pilha como sendo a parte mais cara, e enquanto o segundo artigo não diz isso, acho que é a parte mais cara da criação de objetos. John Rose tem um artigo em que descreve diferentes técnicas para acelerar exceções . (Pré-alocando e reutilizando uma exceção, exceções sem rastreios de pilha, etc.)
Mas ainda assim - acho que isso deve ser considerado apenas um mal necessário, um último recurso. A razão de John fazer isso é emular recursos em outros idiomas que ainda não estão disponíveis na JVM. Você NÃO deve adquirir o hábito de usar exceções para o fluxo de controle. Especialmente por razões de desempenho! Como você mencionou no item 2, você corre o risco de mascarar erros graves no seu código dessa maneira, e será mais difícil manter os novos programadores.
Microbenchmarks em Java são surpreendentemente difíceis de acertar (já me disseram), especialmente quando você entra no território JIT, então duvido muito que o uso de exceções seja mais rápido que o "retorno" na vida real. Por exemplo, suspeito que você tenha algo entre 2 e 5 quadros de pilha em seu teste? Agora imagine que seu código será chamado por um componente JSF implantado pelo JBoss. Agora você pode ter um rastreamento de pilha com várias páginas.
Talvez você possa postar seu código de teste?
fonte
Não sei se esses tópicos estão relacionados, mas uma vez eu quis implementar um truque baseado no rastreamento de pilha do encadeamento atual: queria descobrir o nome do método, que acionava a instanciação dentro da classe instanciada (sim, a ideia é louca, Eu desisti totalmente). Então, descobri que a chamada
Thread.currentThread().getStackTrace()
é extremamente lenta (devido aodumpThreads
método nativo usado internamente).Portanto
Throwable
, Java , correspondentemente, possui um método nativofillInStackTrace
. Eu acho que o killer-catch
block descrito anteriormente de alguma forma desencadeia a execução desse método.Mas deixe-me contar outra história ...
No Scala, alguns recursos funcionais são compilados na JVM usando
ControlThrowable
, o que estendeThrowable
e substitui osfillInStackTrace
da seguinte maneira:Então, eu adaptei o teste acima (a quantidade de ciclos diminui em dez, minha máquina é um pouco mais lenta :):
Então, os resultados são:
Veja, a única diferença entre
method3
emethod4
é que eles lançam diferentes tipos de exceções. Sim,method4
ainda é mais lento quemethod1
emethod2
, mas a diferença é muito mais aceitável.fonte
Fiz alguns testes de desempenho com a JVM 1.5 e o uso de exceções foi pelo menos duas vezes mais lento. Em média: o tempo de execução em um método trivialmente pequeno mais que triplicou (3x), com exceções. Um loop trivialmente pequeno que teve que capturar a exceção viu um aumento de 2x no tempo próprio.
Eu já vi números semelhantes no código de produção e nos micro benchmarks.
As exceções definitivamente NÃO devem ser usadas para qualquer coisa chamada com freqüência. Lançar milhares de exceções por segundo causaria um gargalo enorme.
Por exemplo, usando "Integer.ParseInt (...)" para encontrar todos os valores incorretos em um arquivo de texto muito grande - péssima idéia. (Eu vi esse método utilitário diminuir o desempenho no código de produção)
Usando uma exceção para relatar um valor ruim em um formulário da GUI do usuário, provavelmente não tão ruim do ponto de vista de desempenho.
Seja ou não uma boa prática de design, eu seguiria a regra: se o erro for normal / esperado, use um valor de retorno. Se estiver anormal, use uma exceção. Por exemplo: ao ler entradas do usuário, valores ruins são normais - use um código de erro. Ao passar um valor para uma função de utilitário interno, valores ruins devem ser filtrados chamando código - use uma exceção.
fonte
O desempenho de exceção em Java e C # deixa muito a desejar.
Como programadores, isso nos força a seguir a regra "exceções devem ser causadas com pouca frequência", simplesmente por razões práticas de desempenho.
No entanto, como cientistas da computação, devemos nos rebelar contra esse estado problemático. A pessoa que cria uma função geralmente não tem idéia de com que frequência ela será chamada ou se o sucesso ou o fracasso é mais provável. Somente o chamador tem essas informações. Tentar evitar exceções leva a códigos de API pouco claros, onde, em alguns casos, temos apenas versões de exceção limpas, mas lentas, e em outros casos, temos erros de valor de retorno rápidos, mas desajeitados e, em outros casos, acabamos com os dois . O implementador da biblioteca pode precisar escrever e manter duas versões de APIs, e o responsável pela chamada deve decidir qual das duas versões usar em cada situação.
Isso é uma bagunça. Se as exceções tivessem melhor desempenho, poderíamos evitar esses idiomas desajeitados e usar as exceções como elas deveriam ser usadas ... como um recurso estruturado de retorno de erro.
Eu realmente gostaria de ver os mecanismos de exceção implementados usando técnicas mais próximas dos valores retornados, para que pudéssemos ter um desempenho mais próximo dos valores retornados.
Aqui está um exemplo de código que compara o desempenho da exceção ao desempenho do valor de retorno do erro.
classe pública TestIt {
}
E aqui estão os resultados:
Verificar e propagar valores de retorno adiciona algum custo em relação à chamada nula da linha de base, e esse custo é proporcional à profundidade da chamada. Com uma profundidade de 8 na cadeia de chamadas, a versão de verificação de erro-retorno-valor era cerca de 27% mais lenta que a versão de linha de base, que não verificava os valores de retorno.
O desempenho de exceção, em comparação, não é uma função da profundidade da chamada, mas da frequência da exceção. No entanto, a degradação à medida que a frequência da exceção aumenta é muito mais dramática. Com apenas uma frequência de erro de 25%, o código funcionava 24 vezes mais devagar. Com uma frequência de erro de 100%, a versão da exceção é quase 100 vezes mais lenta.
Isso sugere para mim que talvez estejam fazendo as trocas incorretas em nossas implementações de exceção. As exceções podem ser mais rápidas, evitando caminhadas caras ou transformando-as em verificação de valor de retorno suportada pelo compilador. Até que o façam, estamos impedidos de evitá-los quando queremos que nosso código seja executado rapidamente.
fonte
O HotSpot é capaz de remover o código de exceção para exceções geradas pelo sistema, desde que tudo esteja embutido. No entanto, a exceção criada explicitamente e as que não foram removidas gastam muito tempo criando o rastreamento de pilha. Substitua
fillInStackTrace
para ver como isso pode afetar o desempenho.fonte
Mesmo que lançar uma exceção não seja lento, ainda é uma má idéia lançar exceções para o fluxo normal do programa. Usado desta maneira, é análogo a um GOTO ...
Eu acho que isso realmente não responde à pergunta. Eu imagino que a sabedoria "convencional" de lançar exceções sendo lentas seja verdadeira nas versões java anteriores (<1.4). Criar uma exceção requer que a VM crie o rastreamento de pilha inteiro. Muita coisa mudou desde então na VM para acelerar as coisas e essa é provavelmente uma área que foi aprimorada.
fonte
break
oureturn
nãogoto
.Basta comparar, digamos, Integer.parseInt ao método a seguir, que retorna um valor padrão no caso de dados não analisáveis, em vez de gerar uma exceção:
Contanto que você aplique os dois métodos aos dados "válidos", eles funcionarão aproximadamente na mesma taxa (mesmo que Integer.parseInt consiga manipular dados mais complexos). Mas assim que você tenta analisar dados inválidos (por exemplo, para analisar "abc" 1.000.000 de vezes), a diferença no desempenho deve ser essencial.
fonte
Um ótimo post sobre o desempenho de exceções é:
https://shipilev.net/blog/2014/exceptional-performance/
Instanciando vs reutilizando existentes, com rastreamento de pilha e sem, etc:
Dependendo da profundidade do rastreamento da pilha:
Para outros detalhes (incluindo o montador x64 do JIT), leia a postagem original do blog.
Isso significa que o Hibernate / Spring / etc-EE-shit está lento por causa das exceções (xD) e reescreve o fluxo de controle do aplicativo para longe das exceções (substitua-o por
continure
/break
e retornandoboolean
sinalizadores como em C na chamada de método) para melhorar o desempenho do seu aplicativo 10x-100x , dependendo da frequência com que você os joga))fonte
Alterei a resposta do @Mecki acima para que o method1 retorne um booleano e um check no método de chamada, pois você não pode simplesmente substituir uma exceção por nada. Após duas execuções, o método1 ainda era o mais rápido ou o mais rápido que o método2.
Aqui está um instantâneo do código:
e resultados:
Execução 1
Execução 2
fonte
Uma exceção é destinada ao tratamento de condições inesperadas apenas no tempo de execução .
Usar uma exceção no lugar da validação simples que pode ser feita em tempo de compilação atrasará a validação até o tempo de execução. Por sua vez, isso reduzirá a eficiência do programa.
Lançar uma exceção em vez de usar uma validação simples if..else também tornará o código complexo para escrever e manter.
fonte
Minha opinião sobre a velocidade de exceção versus a verificação de dados programaticamente.
Muitas classes tinham um conversor String to value (scanner / analisador), bibliotecas respeitadas e conhecidas também;)
geralmente tem forma
nome da exceção é apenas um exemplo, geralmente não está marcado (tempo de execução), então lança declaração é apenas minha imagem
às vezes existe uma segunda forma:
nunca jogando
Quando o segundo item não estiver disponível (ou o programador ler muito menos documentos e usar apenas primeiro), escreva esse código com expressão regular. Expressões regulares são legais, politicamente corretas etc:
com esse código, os programadores não têm custo de exceções. MAS TEM um custo MUITO ALTO comparável de expressões regulares SEMPRE versus um pequeno custo de exceção às vezes.
Eu uso quase sempre nesse contexto
sem analisar o stacktrace, etc, acredito que após as palestras de vocês bastante velocidade.
Não tenha medo Exceções
fonte
Por que as exceções devem ser mais lentas do que o retorno normal?
Contanto que você não imprima o rastreamento de pilha no terminal, salve-o em um arquivo ou algo semelhante, o bloco de captura não funciona mais do que outros blocos de código. Portanto, não consigo imaginar por que "lançar novo my_cool_error ()" deve ser tão lento.
Boa pergunta e estou ansioso para obter mais informações sobre este tópico!
fonte