AOP, Validazione e performance: un po’ di considerazioni
In questi giorni ho ripreso in mano la parte di AOP per la validazione dei parametri di input di un metodo, tipicamente quello che si fa è questo:
oppure, evolvendosi leggermente, si può scrivere questo:void StandardValidation( String v ) { if( v == null ) { throw new ArgumentNullException( "v" ); } }
che è effettivamente più elegante e anche leggibile (pensatelo proiettato in produzione e quindi applicato in uno scenario complesso). Resta però il fatto che è da scrivere e che sta li in mezzo ai piedi, ricorrendo a PostSharp si può arrivare a questo:void EnsureValidation( String v ) { Ensure.That( v ).Named( "v" ).IsNotNull(); }
che ha lo stesso identico risultato e inoltre ha il pregio notevole, IMHO, di non avere nulla in mezzo ai piedi.void AspectValidation( [NotNull]String v ) { }
E le perfomance?
tutto bello e funzionale, ma le prestazioni che fine fanno? come al solito dipende da quali sono le nostre necessità: non abbiamo un problema di prestazioni finchè qualcuno non ci dice che va piano.
detto questo però ho voluto provare un test molto casalingo ma ridotto all’osso in modo che l’unica variabile fosse proprio o il codice per la validazione o il codice per il tracing.
Qui di seguito uno screenshot con i risulati, interessanti direi.
- la prima batteria di test è un’iterazione (100k volte) chiamando un metodo con 1 solo parametro, come nel codice di esempio del post, che esegue la validazione tradizionale;
- la seconda è sempre un’iterazione di 100k volte che però chiama un metodo, nei tre modi noti, con 5 parametri… con risultati curiosi: la validazione classica cuba un tempo doppio ma comunque irrilevante, la validazione con le fluent interface, “Ensure”, invece scoppia passando da 198ms a 955ms, pessimo non c’è che dire; la terza invece curiosamente è quella che in termini percentuali perde pochissimo nonostante tempi comunque molto alti in termini assoluti;
Il secondo test, quello del tracing/logging, in effetti fa questo, in questo caso la fa con uno Weaver per PostSharp 1.5, uno Weaver è un plugin per PostSharp che inietta codice custom direttamente a compile time scrivendo esattamente il codice che scriveremmo noi senza aver bisogno del runtime di PostSharp, che infatti non è più una dipendenza a runtime. Il piccolo problema, sempre in attesa di PostSharp 2.0, è che scrivere un Weaver è un delirio :-)
CompileTimeValidate
Una nota infine su quella che secondo me è una delle feature migliori e più sottovalutate di cui ho già parlato. In attesa di “Compiler-As-A-Service” di cui si sa poco o nulla sarebbe un gran bello avere degli attributi che vengono considerati dal compilatore come ad esempio ObsoleteAttribute.
Si… può… fare…!
Non vi tedio con i dettagli tecnici, che ci sono nel post che ho linkato, ma mi soffermo sul fatto che mentre con la versione 1.0 era impossibile fare molte cose a compile time con la 1.5 si può fare pressochè tutto permettendo di intervenire nel processo di compilazione e ad esempio validare anche cose che per il compilatore sarebbe impossibile anche solo prendere in considerazione.
.m