Pergunta

Depois de gastar um pouco de tempo se perguntando por que meu aplicativo estava executando um cenário específico muito lentamente com o depurador anexado, descobri que isso era devido a ter um ponto de interrupção condicional (cuja condição nunca estava sendo atendida). Isso parece razoável, pois a CPU sinalizaria o ponto de interrupção e o VS precisaria avaliar a condição antes de permitir que a execução continuasse. Essas transições devem ser caras.

Presumo que um ponto de interrupção em um caminho de código que não seja executado não tenha impacto no tempo de execução.

Então, minha pergunta é dupla:

  1. Existem recursos que podem quantificar o custo associado a pontos de interrupção condicional e, em caso afirmativo, há algo que se possa fazer para reduzir o custo de avaliação de tempo de execução?
  2. Existe algum custo associado a um ponto de interrupção 'desativado'? Por desativado, quero dizer que vs exibe o marcador do ponto de interrupção na calha com um círculo oco.

É claro que se alguma coisa que mencionei acima não faz sentido, aponte -me na direção certa.

Foi útil?

Solução

É difícil quantificar o custo de um ponto de interrupção condicional. A expressão em um ponto de interrupção condicional é avaliada usando exatamente a mesma semântica como se você tivesse digitado no relógio ou na janela imediata. As expressões dessa natureza não são realmente executadas no programa do cliente, mas tratadas pelo avaliador de expressão específico do idioma. Não é realmente possível perfilar esses tipos de avaliações de maneira significativa.

No entanto, posso listar algumas coisas que são conhecidas por serem mais lentas em uma janela de depuração avaliação

  • Chamadas de função: elas são a coisa mais lenta que você pode fazer, porque a chamada de função exige que o processo de depuração seja reiniciado para que o func avaliação possa ocorrer no processo
  • Comparação de string: sob o capô, eles voltam ao func Evalals

Quanto aos pontos de interrupção desativados, não, eles não afetam a execução do aplicativo.

Outras dicas

Uma coisa a ser observada (que aprendi da maneira mais difícil) é garantir que você coloque == ao comparar uma variável com um valor e não o único =

O editor do ponto de interrupção não avisa você, mas quando o ponto de interrupção é avaliado, a variável é alterada! Levei um tempo para depurar meu código com esse!

Além disso, se eu realmente precisar do código de interrupção condicional para o código BEBUG; Adicionei a condição ao código e, em seguida, adiciono algo como string stop = "aqui"; E coloque um ponto de interrupção normal lá - acho que o código é mais rápido na época.

Eu li algum lugar em que há suporte de hardware para esses pontos de interrupção, para que o uso de menos de X pontos de interrupção condicional de um certo tipo seja essencialmente gratuito, mas acima disso, ele precisa usar mais software. (Otoh, isso foi para aplicativos nativos, não tenho certeza sobre essas coisas novas.)

Os pontos de interrupção desabilitados devem tomar afetar as coisas, eles apenas ocorrem alguns recursos de memória e GUI no IDE.

Também notei que os pontos de interrupção condicionais são caros e chegaram à mesma conclusão que você. Não consigo imaginar qualquer motivo pelo qual um ponto de interrupção desativado causaria qualquer desaceleração, pois eu esperaria que fosse apenas uma coisa do editor, um atalho para ativar um ponto de interrupção, caso você precise.

O que eu faço quando estou em uma situação como a sua é fazer uma macro assert. (você pode usar o afirmar Macro que o Visual Studio oferece, mas eu não gosto). Peça à sua macro verifique a condição que deseja e depois ligue Debugbreak Se falhar. No Realease, ou construção não verificada do seu aplicativo, afirme nada para nada, para que seu código não seja impactado.

Uma macro simples afirma:

#ifdef _DEBUG
#define assert(x)\
do{\
  if(!(x)){DebugBreak();}\
}while(0)
#else
#define assert(x)
#endif

e chame como:

assert(pValue != NULL && "A bad parameter was passed to the function");

Você pode colocar mais código na falha antes do Debugbreak (como imprimir a condição que falhou com #X e/ou o número da linha/arquivo com ____File____ e ____line____ para poder clicar duas vezes na mensagem). Você pode escrever mensagens para o log de depuração com OutputDebugString e até verifique se um depurador está anexado com IsdebuggerPresent Para adaptar ainda mais sua afirmação. Também gosto de usar o formato && string para fornecer um pouco mais de informações sobre a afirmação específica.

Há algumas coisas a serem cuidadosas ao usar afirmam. Primeiro, não coloque nenhum código que seja executado na macro, pois será retirado em uma construção não depra. Pelas mesmas razões, não coloque o código que tenha efeitos colaterais. Além disso, você não deseja ligar para o debugbreak () quando um depurador não estiver anexado porque ele essencialmente joga uma exceção, que, se não for capturada, encerrará o aplicativo.

  1. Tente colocar o ponto de interrupção no seu código para testar o desempenho. POR EXEMPLO

    Stopwatch st = new Stopwatch();
    st.Start();
    if(my condition)
    {
      st.Stop();
      Debugger.Break();
    }
    

    Não, não é exatamente o mesmo, mas perto o suficiente.

  2. Não - um ponto de interrupção desativado não está presente no programa de execução. Está apenas armazenado nos metadados do VS para sua conveniência.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top