Codice duplicato per evitare un calo delle prestazioni dovuto alle chiamate di funzione? [chiuso]

-2

Ho una semplice lista in Java che devo cercare usando uno dei due metodi. Il primo metodo restituisce semplicemente la posizione nell'elenco del primo elemento corrispondente. Il secondo filtra tutti gli elementi che non corrispondono. Ecco alcuni pseudo-ish-code:

public int positionMatch(String search) {

    for (Element e: myList) {
        if (matches(search, e)) return position(e);
    }
}

public List<Element> filterMatch(String search) {

    for (Element e: myList) {
        if (matches(search, e)) filteredList.add(e);
    }
}

public boolean matches(String search, Element element) {
    // Some logic to determine whether or not the element
    // matches the search term, which is the core functionality
    // shared across all search types. This is ~100 LOC.
}

Il problema arriva con le chiamate a match(String search, Element e) . La mia lista è di decine di migliaia di elementi, e avere una chiamata di funzione per elemento sta causando una lentezza estrema (di un fattore di circa 500). Il problema è che la logica di ricerca in matches(search, e) è condivisa, indipendentemente da come vengono restituiti gli elementi (come posizione o come elenco filtrato), quindi non ha senso duplicare il codice per ogni metodo positionMatch e filterMatch (e qualsiasi altro tipo di ricerca che potrebbe essere aggiunto in seguito). Tuttavia, il rendimento delle prestazioni in non la duplicazione del codice non è accettabile.

Un altro problema è che, almeno in Java, non puoi avere più tipi di ritorno (o almeno non sarebbe molto carino o intuitivo con i generici). Pertanto, non posso semplicemente avere un tipo di funzione match(String search, List<Element> elements, SearchType searchType) che restituisca un int position o List<Element> filteredList .

Va bene in questo caso duplicare il codice attraverso positionMatch e filterMatch per annullare le decine di migliaia di chiamate di funzione al codice comune che causa la lentezza?

Oppure mi manca qualcosa di molto semplice qui che potrebbe evitare la duplicazione e non causare problemi di prestazioni? PS - Al momento sto scrivendo una domanda su CodeReview per vedere se esiste un modo specifico di Java per evitare questo problema ...

    
posta Chris Cirefice 30.05.2016 - 22:50
fonte

1 risposta

4

Wow. Le chiamate di funzione sono più lente delle ricerche di stringhe? Quale implementazione di Java stai usando?

Ero solito scrivere assembly e il manuale indicava il numero di "clic" che ciascuna istruzione assumeva sul processore. Quei giorni sono finiti, ma se dovessi indovinare quanti clic fanno varie operazioni, direi qualcosa del tipo:

bitwise operations: 1
function call: 2
addition/subtraction: 2
multiplication/division: 10
boxing/unboxing: 10 per box/unbox
find-character-in-string: string-length * 3
regex processing: string-length * 100

Quando ho provato il processore Java RegEx su quello Perl nel 2004, Perl era circa 100 volte più veloce. Ho provato solo con ASCII e Java utilizza internamente UTF-16, quindi questo potrebbe essere parte del motivo.

Se dovessi delegare attraverso 10 funzioni a diversi livelli nella gerarchia dell'eredità, che potrebbe valere la pena di avere sul tuo radar se non usi espressioni regolari o boxe ovunque.

Inoltre, se stai abbinando una stringa fissa all'interno di un'altra stringa, presumo che tu stia utilizzando oneString.indexOf (anotherString) incorporato perché è dannatamente veloce.

Hai usato un profiler per vedere dove sta effettivamente accadendo la lentezza? O capire il più piccolo pezzo di codice che puoi commentare per farlo funzionare velocemente. Se sei su Windows, scrivere sul terminale è estremamente costoso (forse segna 50 "clic" nella mia lista sopra), ma su un sistema basato su * nix, per scadenze grossolane dovresti essere in grado di:

long startTime = System.nanoTime();
// do something
System.out.println("That thing took " + (System.nanoTime() - startTime));

In Java, you can't have multiple return types (or at least it wouldn't be very pretty or intuitive using generics). Thus, I can't just have a match(String search, List elements, SearchType searchType) kind of function that would return either an int position or List filteredList

public Or<List<Element>,Integer> match(...)

UncleJim ha o sotto il licenza apache che puoi copiare nel tuo progetto (con una nota di attribuzione). Se questo è troppo supponente per te, c'è OneOf2 dove entrambe le opzioni sono "corrette" (un tipo di unione). Se vuoi fare la cosa monade c'è rxeither che alcune persone utilizzano su Android.

    
risposta data 30.05.2016 - 23:03
fonte

Leggi altre domande sui tag