In un programma che sto scrivendo sto facendo un sacco di manipolazione delle stringhe. Sto cercando di aumentare le prestazioni e mi chiedo se l'utilizzo di array di caratteri mostrerà un aumento delle prestazioni decente. Eventuali suggerimenti?Java Optimization String vs Char Arrays
risposta
Che tipo di manipolazione stai facendo? Puoi pubblicare un esempio di codice?
Si consiglia di dare un'occhiata a StringBuilder che implementa CharSequence per migliorare le prestazioni. Non sono sicuro di volere rotolare il tuo. StringBuilder non è thread safe btw ... se vuoi sicurezza thread look a StringBuffer.
Se hai bisogno di thread-safety, c'è una possibilità non banale che dovrai fare di più che semplicemente rilasciare un 'StringBuffer'. Potresti evitare deadlock e condizioni di gara, ma i risultati probabilmente non corrisponderanno a quanto ti aspettavi. –
Grazie, reimplementerò e pubblicheremo i miei risultati. – ThePinkPoo
@Hank: con un aggiornamento non banale, avvolgi il tuo 'sincronizzato (thebuffer) {...}' attorno ad esso, ma non hai bisogno di quel genere di cose troppo spesso. In effetti, è per questo che è stato introdotto 'StringBuilder'; per sbarazzarsi del costo di tenere serrature a tutti quando non è necessario (cioè quasi tutto il tempo). –
La stringa è già implementata come un array di caratteri. Che cosa hai in programma di fare diversamente? Ad ogni modo, tra questo e il fatto che GC per oggetti effimeri sia estremamente veloce, sarei sorpreso se riuscissi a trovare un modo per aumentare le prestazioni sostituendo gli array di caratteri.
Il consiglio di Michael Borgwardt su piccoli array di caratteri e l'uso di StringBuilder e StringBuffer è molto buono. Ma per me la cosa principale è cercare di non indovinare cosa è lento: fare misurazioni, usare un profiler, ottenere alcuni fatti precisi. Perché di solito le nostre supposizioni sulla performance si rivelano sbagliate.
Quando si dispone di un numero molto elevato di stringhe brevi, utilizzare char[]
invece può risparmiare un bel po 'di memoria, il che significa anche maggiore velocità a causa di meno errori di cache.
Ma con stringhe di grandi dimensioni, la cosa principale da evitare è evitare la copia non necessaria risultante dall'immutabilità di String
. Se fai molti concatenamenti o sostituzioni, usare StringBuilder
può fare una grande differenza.
Michael, potresti approfondire la questione sostituendo Stringhe con char []? Char [] occupa uno spazio leggermente inferiore rispetto a un'istanza String, tuttavia char [] non viene internalizzato e per molte stringhe brevi la probabilità che alcune stringhe siano uguali e che vengano internalizzate (ovvero JVM manterrà una singola copia) è molto più alto che per poche stringhe lunghe. –
@Totophil: Dipende davvero dal tipo di stringhe con cui si lavora e da ciò che si fa con esse; Se si usano rappresentazioni mutabili, l'internamento diventa irrilevante. –
Michael, d'accordo, dipende davvero dalle specifiche dello scenario. E l'unico scenario che mi viene in mente è quando il software ha bisogno di fare molte manipolazioni di stringhe "in atto". Ma l'approccio non sarà di alcun aiuto nell'affrontare i costi generali delle stringhe derivanti dalla concatenazione, dalle ricerche e dai confronti. –
Ecco un estratto dal full source of String class da JDK 6.0:
public final class String implements java.io.Serializable,
Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
Come si può vedere internamente il valore è già memorizzato come un array di caratteri. Una serie di caratteri come una struttura dati ha tutti i limiti della classe String per la maggior parte delle manipolazioni di stringhe: gli array Java non crescono, cioè ogni volta (ok, potrebbe non essere ogni volta) la stringa dovrebbe crescere di cui avresti bisogno allocare un nuovo array e copiare il contenuto.
Come suggerito in precedenza, è opportuno utilizzare StringBuilder o StringBuffer per la maggior parte delle manipolazioni di stringhe.
Infatti il codice seguente:
String a = "a";
a=a+"b";
a=a+"c";
Quando viene compilato saranno convertiti automaticamente per utilizzare StringBuilder, questo può essere facilmente controllato con l'aiuto di javap.
Come regola empirica, è raramente consigliabile dedicare del tempo a migliorare le prestazioni delle classi Java principali, a meno che non siate esperti di livello mondiale sull'argomento, semplicemente perché questo codice è stato scritto dagli esperti di livello mondiale nel primo posto.
Hai profilato la tua domanda? Sai dove sono i colli di bottiglia? Questo è il primo passo se la performance è sub par. Bene, questo e definendo quali sono le metriche di performance accettabili.
Dopo aver profilato alcuni compiti, si avranno percentuali di tempo spesi a fare le cose. Se passi molto tempo a manipolare le stringhe, forse puoi iniziare a mettere in cache alcune di quelle manipolazioni?Stai facendo alcuni di essi ripetutamente quando li fai solo una volta sarebbe sufficiente (e poi usi di nuovo quel risultato più tardi quando è necessario)? Stai copiando le stringhe quando non ne hai bisogno? Ricorda, java.lang.String è immutabile, quindi non può essere modificato direttamente.
Ho trovato diverse volte durante l'ottimizzazione/prestazioni dei sistemi di tweaking su cui lavoro che non so da dove viene la lentezza proviene da istintivamente. Ho visto altri (e, vergognosamente, me stesso) passare giorni a ottimizzare qualcosa che non mostra alcun guadagno - perché non era il collo di bottiglia originale, ed era in realtà meno dell'1% del tempo trascorso.
Spero che questo ti aiuti a orientarti nella giusta direzione.
Ho profilato e non è stato molto informativo dato che la mia complessità è piuttosto ridotta. So dal profilo che i metodi di stringa lo stavano uccidendo, anche i miei loop all'interno del codice. Quindi ho intenzione di srotolare alcuni dei loop e usare StringBuilder – ThePinkPoo
@ThePinkPoo: se le operazioni String lo stanno uccidendo, la cosa migliore da fare è provare a ridurre il numero di operazioni String che stai facendo. Questo può essere fatto attraverso la memorizzazione nella cache o un comportamento simile. Ci scusiamo per il fatto che tu non abbia un profilo - lo vedo spesso su varie pagine di forum (qui incluso), e volevo assicurarmi che lo stavi facendo. :) In bocca al lupo. – aperkins
- 1. java: Elenco dei String Arrays e rimuovere
- 2. JAVA String to char
- 3. const char * myVar vs. const char myVar []
- 4. C# Array - string [] [] vs string [,]
- 5. Java println (charArray + String) vs println (charArray)
- 6. Char Array VS Char *
- 7. Confronto Char/String
- 8. ambiguo chiamata (conversione da char * a lambda vs std :: string)
- 9. SQLite3 query optimization join vs subselect
- 10. Java - strano comportamento static String - new String ("xxx") vs "xxx"
- 11. const constexpr char * vs. constexpr char *
- 12. Deduplicazione Java 8 String vs. String.intern()
- 13. Converti char [] array di String
- 14. AS3 Vector of Arrays
- 15. uint8_t vs char unsigned
- 16. char vs wchar_t
- 17. Cosa ha più senso: char * string o char * stringa?
- 18. Conversione preferita da char (non char *) a std :: string
- 19. jQuery Optimization
- 20. Come convertire std :: string in const char *?
- 21. Come convertire Platform :: String in char *?
- 22. string e const char * e .c_str()?
- 23. const unsigned char * a std :: string
- 24. Come convertire char * a un sistema :: string^
- 25. Come concatenare char e string su iPhone?
- 26. Come convertire v8 :: String a const char *
- 27. String Unicode rimuove char dalla stringa
- 28. Perché usare char [] invece di String?
- 29. java String constructor logic
- 30. Come convertire da char a Piattaforma :: String^(C++/CLI)
@ThePinkPoo: la tua domanda è priva di requisiti: cosa si suppone che la stringa contenga? L'intera gamma di Unicode (nel qual caso l'utilizzo di char [] si rivelerà un grave problema poiché un Java * char * è ** TOTALLY INADEQUATE ** per rappresentare i nuovi codepoint Unicode introdotti in Unicode 3.1 e successivi)? Solo (un sottoinsieme di) ASCII? In quest'ultimo caso è possibile ri-implementare l'intera classe String supportata solo da byte e si può fare molta ottimizzazione * very * nifty. Ci sono stato, fatto ciò, elaborando centinaia di megabyte di file di testo ASCII in Java ... – SyntaxT3rr0r