La convalida delle credenziali può essere eseguita in pochi millisecondi per un miliardo di utenti. Questo a causa di:
- Indicizzazione (riduce il numero di operazioni a soli 30, per 1 miliardo di utenti). Ulteriori dettagli: link
- Cache (farà in modo che queste 30 operazioni non colpiscano il disco il più delle volte)
Nel mondo reale, ciò richiederebbe 1 - 300 millisecondi (paio di accessi al disco + accodamento + concorrenza a causa di registrazioni costanti e modifiche della password).
Esempio estremo:
Se l'organizzazione può permettersi macchine con memoria di grandi dimensioni (ad esempio, macchine con una memoria da 200 GB), ciò richiederebbe un tempo quasi zero.
Pronuncia stringa contenente nome utente: password (salata + password con hash nei sistemi reali) sono memorizzati in una mappa. La ricerca di questa mappa per scoprire se una determinata combinazione di nome utente e password è valida o meno, richiederebbe quasi il non-tempo. Questo perché Hashtable può controllare la presenza o l'assenza nella complessità temporale O (1).
In altre parole, non importa se il sistema ha 100 utenti o 100 milioni o miliardi; le password possono essere convalidate in un tempo vicino allo zero.
Il codice seguente lo dimostra con un set di dati più piccolo (60 milioni di username / password e 20 milioni di utenti che si collegano). Ci sono voluti solo 0,002 millisecondi per validazione.
Sun Mar 20 18:40:11 IST 2016::Starting
Sun Mar 20 18:43:03 IST 2016::Generated test data, count 40000000
Doing 20000000 validations.
Sun Mar 20 18:43:30 IST 2016 Done in 26860 msecs.
0.001343 milliseconds per validation
Codice:
import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class UserValidator {
Set<String> validCredentials=new HashSet<>();
long numCredentials = 1000*1000*60;
Random rnd = new Random();
char[] validChars=null;
public UserValidator(){
String chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*~*()";
validChars = chars.toCharArray();
}
String generateRandomString(int len){
StringBuilder sb = new StringBuilder( len );
for( int i = 0; i < len; i++ )
sb.append( validChars[ rnd.nextInt(validChars.length) ] );
return sb.toString();
}
String getRansomString(){
int len = 4;
len = len+rnd.nextInt(20);
return generateRandomString(len);
}
void generateTestData(){
for(long i=0;i<numCredentials;i++){
String username=getRansomString();
String password=getRansomString();
String credentials=username+":::"+new String(username+":"+password).hashCode();
validCredentials.add(credentials);
}
}
boolean isValidUser(String user, String password){
String credentials=user+":::"+new String(user+":"+password).hashCode();
return validCredentials.contains(credentials);
}
public static void main(String[] args) {
UserValidator u = new UserValidator();
System.out.println(new Date().toString()+"::Starting");
u.generateTestData();
System.out.println(new Date().toString()+"::Generated test data, count "+u.validCredentials.size());
int lookups=20*1000*1000;
System.out.println("Doing "+lookups+" validations.");
long timeStart = new Date().getTime();
for(int i=0;i<lookups;i++){
u.isValidUser(u.getRansomString(), u.getRansomString());
}
long timeEnd = new Date().getTime();
long timeSpent = (timeEnd-timeStart);
System.out.println(new Date().toString()+" Done in "+timeSpent+" msecs.");
System.out.println((double)timeSpent/(double)lookups +" milliseconds per validation");
}
}