API Roslyn:perché PVS-Studio ha analizzato il progetto così a lungo

 C Programming >> Programmazione C >  >> Tags >> API
API Roslyn:perché PVS-Studio ha analizzato il progetto così a lungo

Quanti di voi hanno utilizzato librerie di terze parti durante la scrittura del codice? È una domanda accattivante. Senza librerie di terze parti lo sviluppo di alcuni prodotti sarebbe ritardato per molto, molto tempo. Si dovrebbe reinventare la ruota per risolvere ogni problema. Quando utilizzi librerie di terze parti, oltre agli ovvi vantaggi, ti imbatti ancora in alcune insidie. Recentemente PVS-Studio per C# ha anche affrontato una delle carenze. L'analizzatore non è riuscito a completare l'analisi di un progetto di grandi dimensioni per molto tempo. Era dovuto all'uso del metodo SymbolFinder.FindReferencesAsync dell'API Roslyn nella diagnostica V3083.

La vita in PVS-Studio procedeva come al solito. Abbiamo continuato a scrivere nuove diagnostiche, a migliorare l'analizzatore, a pubblicare nuovi articoli. Scoppio! Uno degli utenti dell'analizzatore aveva l'analisi in corso su un grande progetto durante il giorno e non poteva terminare in alcun modo. Allarme! Allarme! Tutte le mani sul ponte! Dopo aver ricevuto i file di dump dall'utente, abbiamo spostato la nostra attenzione per scoprire i motivi di una lunga analisi. Si è scoperto che la diagnostica 3 C# ha funzionato più a lungo. Uno di questi era il numero diagnostico V3083. Questa diagnostica ha già ricevuto la nostra speciale attenzione. È giunto il momento di intraprendere azioni specifiche! V3083 avverte di chiamate di eventi C# errate. Ad esempio, nel codice:

public class IncorrectEventUse
{
  public event EventHandler EventOne;  
  protected void InvokeEventTwice(object o, Eventers args)
  {
    if (EventOne != null)
    {
      EventOne(o, args);        
      EventOne.Invoke(o, args);
    }
  }
}

V3083 punterà alle chiamate ai gestori di eventi di EventOne in InvokeEventTwice metodo. Puoi saperne di più sui motivi per cui questo codice è pericoloso nella documentazione di questa diagnostica. Dall'esterno, la logica del V3083 è molto semplice:

  • trova una chiamata a un evento;
  • controlla se questo evento è stato chiamato correttamente;
  • emette un avviso se l'evento viene chiamato in modo errato.

Ora, quando sappiamo che è così semplice, diventa ancora più interessante capire il motivo del lungo lavoro diagnostico.

Motivo del rallentamento

In effetti, la logica è un po' più complicata. In ogni file per ogni tipo V3083 crea un solo avviso dell'analizzatore per un evento. In questo avviso, V3083 scrive tutti i numeri di riga dei casi in cui l'evento viene chiamato in modo errato. Questo aiuta a navigare in vari plugin:Visual Studio, Rider, SonarQube. Si scopre che il primo passo è trovare tutti i luoghi in cui viene chiamato l'evento. Per un'attività simile, l'API Roslyn disponeva già di SymbolFinder.FindReferencesAsync metodo. È stato utilizzato in V3083, per non reinventare la ruota.

Molte linee guida consigliano di utilizzare questo metodo:primo, secondo, terzo [RU] e altri. Forse, in alcuni casi semplici, la velocità di questo metodo è sufficiente. Tuttavia, maggiore è la base di codice del progetto, maggiore sarà l'esecuzione di questo metodo. Ne eravamo sicuri al 100% solo dopo aver cambiato V3083.

V3083 accelera dopo la modifica

Se si modifica il codice di una diagnostica o il core dell'analizzatore, è necessario verificare che nulla di ciò che funzionava prima sia danneggiato. Per fare ciò, disponiamo di test positivi e negativi per ogni diagnostica, unit test per il core dell'analizzatore e un database di progetti open source. Ci sono quasi 90 progetti in esso. Perché abbiamo bisogno di un database di progetti open source? Lo usiamo per eseguire il nostro analizzatore per testare lo strumento in condizioni sul campo. Anche questa corsa serve come ulteriore controllo che non abbiamo rotto nulla nell'analizzatore. Abbiamo già eseguito un'analisi dell'analizzatore su questa base prima della modifica del V3083. Tutto quello che dovevamo fare era fare una corsa simile dopo aver cambiato V3083 e capire il guadagno di tempo. I risultati si sono rivelati una piacevole sorpresa! Abbiamo ottenuto un aumento del 9% sui test senza utilizzare SymbolFinder.FindReferencesAsync . Queste cifre potrebbero sembrare insignificanti per qualcuno. Bene, controlla le specifiche del computer che abbiamo usato per le misurazioni:

Si spera che anche gli scettici più cinici abbiano pienamente compreso la portata del problema che viveva tranquillamente nella diagnostica del V3083.

Conclusione

Lascia che questa nota sia un avvertimento per tutti coloro che utilizzano l'API Roslyn! In questo modo non commetterai i nostri errori. Non si applica solo a SymbolFinder.FindReferencesAsync metodo. Riguarda anche altri Microsoft.CodeAnalysis.FindSymbols.SymbolFinder metodi di classe che utilizzano lo stesso meccanismo.

Consiglio vivamente anche a tutti gli sviluppatori di rivedere le librerie che utilizzano. Lo dico per un motivo! Perché è così importante? Dai un'occhiata alle nostre altre note per scoprire perché:primo, secondo. Trattano questo argomento in modo più dettagliato.

Oltre allo sviluppo della diagnostica, ci siamo impegnati a ottimizzare PVS-Studio. Non perdere gli articoli e le note futuri per scoprire le modifiche!

Non abbiamo rilasciato la correzione diagnostica V3083, quindi l'analizzatore versione 7.12 funziona utilizzando SymbolFinder.FindReferencesAsync .

Come accennato in precedenza, abbiamo riscontrato il rallentamento dell'analizzatore in altre due diagnostiche C# oltre a V3083. Come pensi, quali sono questi diagnostici? Solo per motivi di interesse, lascia le tue idee nei commenti. Quando ci saranno più di 50 suggerimenti, aprirò il velo della segretezza e chiamerò i numeri di questi diagnostici.