2015-06-03 9 views
7

Un collega rilevare il seguente frammento dal Log4J 2.3 code:Log4J 2 configurazione di monitoraggio e bitwise confronto

/** 
    * Called to determine if the configuration has changed. 
    */ 
@Override 
public void checkConfiguration() { 
    final long current = System.currentTimeMillis(); 
    if (((counter.incrementAndGet() & MASK) == 0) && (current >= nextCheck)) { 
     LOCK.lock(); 
     try { 
      nextCheck = current + intervalSeconds; 
      if (file.lastModified() > lastModified) { 
       lastModified = file.lastModified(); 
       for (final ConfigurationListener listener : listeners) { 
        final Thread thread = new Thread(new ReconfigurationWorker(listener, reconfigurable)); 
        thread.setDaemon(true); 
        thread.start(); 
       } 
      } 
     } finally { 
      LOCK.unlock(); 
     } 
    } 

Dove counter è un AtomicInteger campo, MASK è impostato 0x0f e nextCheck è long.

Per quanto posso capire, questo metodo controlla se o meno per ricaricare la configurazione, ma lo fa solo quando il valore s' il counter è divisibile per 16 e il prossimo periodo di controllo della configurazione è trascorso.

Perché questo bit è AND?

Dato che l'incrementAndGet è sincronizzato per l'istanza counter, potrebbe essere considerato un meccanismo di regolazione "economico"? O forse il numero di volte che checkConfiguration viene chiamato durante il periodo "tipico" nextCheck è molto più del necessario, quindi l'AND bit a bit è lì come un trucco delle prestazioni (di nuovo, la limitazione?).

+0

"forse il numero di volte in cui checkConfiguration è chiamato [...] è molto più del necessario" - Penso che il codice implichi proprio questo. È necessario scoprire dove/perché viene chiamato questo metodo. Ovviamente, sono anche preparati per le esecuzioni concorrenti di 'checkConfiguration'. – JimmyB

+0

Penso che l'incremento 'counter' sia parzialmente un problema di sincronizzazione: consente alle chiamate sulla stessa istanza di eseguire il successivo controllo di aggiornamento in modo thread-safe, oltre a ridurre le chiamate al blocco successivo (che è bloccato da un'istanza' ReentrantLock' –

+1

Penso di averlo trovato: 'org.apache.logging.log4j.core.Logger.logMessage (String, Level, Marker, Message, Throwable)' chiama incondizionatamente 'checkConfiguration()', quindi farebbe un * lotto * delle chiamate – JimmyB

risposta

0

Sì, questo è un meccanismo di regolazione. In Log4j 2.3 questo metodo è stato chiamato per ogni evento di registro. AND bit a bit significa che il resto del controllo viene eseguito solo una volta ogni 16 eventi del registro.

Come notato nei commenti, è discutibile quanto sia efficace in termini di aumento delle prestazioni. La chiamata a System::currentTimeMillis non è gratuita e in condizioni di contesa pesante AtomicLong::incrementAndGet prestazioni anche degrades.

Da Log4j 2.5 il codice sopra non esiste più (vedere LOG4J2-89). È stato sostituito da una classe WatchManager che controlla se il file di configurazione è stato modificato in un thread in background.