2 Stimmen

ANDROID Wie man String-Zuweisungen reduziert

Ich habe es geschafft, meine Zuweisungen mit DDMS auf fast nichts zu reduzieren (tolles Werkzeug), dadurch wurden meine GCs drastisch auf etwa 1 oder 2 alle 3 Minuten reduziert. Trotzdem bin ich nicht zufrieden, weil sie normalerweise eine spürbare Verzögerung im Spiel verursachen (auf einigen Telefonen), wenn man damit interagiert.

Mit DDMS weiß ich, was die Zuweisungen sind, es handelt sich um Strings, die von Integern konvertiert werden, die zur Anzeige von Spielinformationen im HUD verwendet werden.

Im Grunde mache ich das hier:

int playerScore = 20929;
String playerScoreText = Integer.toString(playerScore);
canvas.drawText(playerScoreText, xPos, yPos);

Dies geschieht einmal pro Rahmenaktualisierung und das HUD-System ist modular, sodass ich Dinge einstecke, wenn ich sie brauche, was dazu führen kann, dass 4 oder 5 HUD-Elemente Strings und AbstractStringBuilders in DDMS zuweisen.

Gibt es einen Weg, diese weiter zu reduzieren oder alle String-Zuweisungen zu eliminieren und einfach ein String-Objekt wiederzuverwenden?

Vielen Dank, Albert Pucciani

1 Stimmen

Wenn die GC Verzögerungen verursacht, scheint es, als würden Sie etwas falsch machen. Das Konvertieren einer Ganzzahl in einen String ist ein äußerst triviales Verfahren, und es gibt NICHTS, was Sie dagegen tun können, da es LETZTLICH irgendwo in einen String konvertiert werden muss.

0 Stimmen

DrawText(..) verwendet auch char[]. Verwenden Sie stattdessen - siehe Antwort von @tp0w3rn.

0 Stimmen

@Falmarri: Es sind nicht die Zuweisungen, die das Problem sind, sondern: 1 Zeichenkettenzuweisung x 5 HUD-Elemente x 40 Mal pro Sekunde x 10 Sekunden = ergibt eine Menge Müll, der übrig bleibt. @Peter Knego: Danke, ich habe tp0w3rn's Antwort unten gar nicht bemerkt, bis ich deinen Beitrag wieder gelesen habe.

5voto

tp0w3rn Punkte 68

Beim Lesen deiner Frage erinnerte ich mich an einen der Artikel von Robert Green, den ich vor einiger Zeit gelesen habe. Er behandelt dein Problem fast identisch. http://www.rbgrn.net/content/290-light-racer-20-days-32-33-getting-great-game-performance. Springe zu Tag 33 und fange an zu lesen.

0 Stimmen

Toll, funktioniert perfekt, danke nochmal! Ich würde für dich abstimmen, aber ich habe nicht genug Rufpunkte.

0 Stimmen

Sie können mich immer noch als die richtige Antwort akzeptieren :) . Freut mich, dass ich helfen konnte, ich bin auch neu hier.

5voto

Vit Khudenko Punkte 27989

Bitte denk an den letzten int-Score und seine String-Repräsentation. Überprüfe auf einem neuen Frame, ob der Score gleich ist. Wenn er gleich ist, muss keine neue Zeichenfolge erstellt werden - verwende einfach die alte.

0 Stimmen

Hallo, ich habe das zwar in Betracht gezogen, aber es würde immer noch eine Menge String-Allokationen geben, da sich die HUD-Elemente oft ändern, möglicherweise 4-5 Mal pro Sekunde (wie Timer, Serien, Punkteänderungen usw...) und wenn ich die Debug-Konsole aktiviere, wird es noch schlimmer, da ich eine Menge Strings verwende.

0voto

Andi Jay Punkte 5652

Hier ist, was ich in der Vergangenheit gemacht habe. Dies beseitigt String-Allokationen.

Ich erstelle ein char[], das mindestens so groß ist wie die maximale Anzahl von Zeichen, die Sie auf dem Bildschirm anzeigen müssen. Das bedeutet, dass Sie einen maximalen Highscore auswählen sollten, der im Spiel erreichbar ist. Auf die aktuelle Weise können Sie einen Score anzeigen, der so hoch ist wie 2^31-1, was wahnsinnig groß ist und im Hinblick auf das Spiel nicht praktisch ist. Denken Sie daran, dass dies Ihr Spiel ist, daher ist es in Ordnung, den Maximalscore in einem vernünftigeren Rahmen im Kontext des Spiels zu begrenzen. Wählen Sie eine Zahl, die virtuell unmöglich zu erreichen ist. Durch Festlegen dieser Grenze müssen Sie dann nicht mehr mit der Konvertierung großer Ganzzahlen in String-Objekte herumhantieren.

Hier ist, was erforderlich ist:

Zunächst müssen Sie in der Lage sein, die Ziffern einer Ganzzahl zu separieren und in Zeichen ohne Erstellung von String-Objekten zu konvertieren. Angenommen, Sie möchten die Ganzzahl 324 in drei separate Zeichen '3','2','4' umwandeln, die im Text char[] platziert werden sollen. Eine Möglichkeit, dies zu tun, besteht darin, den Wert 324 zu nehmen und ein Modulo 10 auszuführen, um die niedrigste Ziffer zu erhalten. Also 324%10 = 4. Teilen Sie dann den Wert durch zehn und führen Sie erneut ein Modulo 10 aus, um die nächste Ziffer zu erhalten. Also (324/10)%10 = 2 und (324/100)%10 = 3.

int score = 324;
int firstPlaceInt = score%10; // firstPlace wird 4 sein
int tensPlaceInt = (score/10)%10; // tensPlace wird 2 sein
int hundresPlaceInt = (score/100)%10; // hundredsPlace wird 3 sein

Sie müssen dies in einer Schleife tun, aber dies drückt die Idee dessen aus, was Sie hier versuchen zu tun.

Dann können Sie diese Ziffern mit einem Zeichenverweis in chars umwandeln. Eine Möglichkeit, dies zu tun, besteht darin, diese Zeichenzuordnung zu erstellen, indem Sie ein char[] der Größe 10 erstellen und die Werte 0 - 9 an den Indizes 0 - 9 platzieren.

char[] charMap = {'0','1','2','3','4','5','6','7','8','9',};

Also dies zu tun:

int score = 324;
char firstPlace = charMap[score%10];
char tenslace = charMap[(score/10)%10];
char hundredsPlace = charMap[(score/100)%10];

Wird die Zeichen erzeugen, die Sie für die 3 Ziffern im Score benötigen.

Nach alledem würde ich den höchsten Score auf sagen wir 99.999 begrenzen (oder was auch immer in Ihrem Spiel sinnvoll ist). Dies bedeutet, dass die größte "Zeichenkette", die ich anzeigen muss, "Score: xx,xxx" ist. Dies erfordert ein char[] (nennen wir es in diesem Beispiel text) der Größe 13. Initialisieren Sie die ersten 7 Zeichen mit "Score: ", diese müssen nie geändert werden.

char[] text = new char[13];
text[0] = 'S';
text[1] = 'c';
text[2] = 'o';
text[3] = 'r';
text[4] = 'e';
text[5] = ':';
text[6] = ' ';

Die nächsten 6 werden je nach Punktzahl variieren. Beachten Sie, dass Sie möglicherweise nicht alle 6 dieser verbleibenden Zeichen ausfüllen müssen. Daher müssen Sie eine int (nennen wir sie in diesem Beispiel scoreCount), die Ihnen anzeigt, wie viele Zeichen im char[] tatsächlich relevant für den aktuellen Punktestand im Spiel sind. Angenommen, ich muss "Score: 324" anzeigen, dies erfordert nur 10 Zeichen aus den 13. Schreiben Sie die 3 Zeichen für den Score von 324 in char[7] bis char[9] und setzen Sie scoreCount auf 10, um die Anzahl der gültigen Zeichen im char[] anzugeben.

int scoreCount = 7;
text[9] = charMap[score%10]; // dies ist firstPlace
text[8] = charMap[(score/10)%10]; // dies ist tensPlace
text[7] = charMap[(score/100)%10]; // dies ist hundredsPlace
scoreCount = 10;

Sie müssen dies wahrscheinlich in einer Schleife tun, aber dies sollte die allgemeine Idee dessen ausdrücken, was Sie hier versuchen zu tun.

Danach können Sie einfach drawText(char[] text, int index, int count, float x, float y, Paint paint) verwenden. index wird 0 sein und count wird scoreCount sein, was anzeigt, wie viele Zeichen in text gezeichnet werden sollen. In dem obigen Beispiel ist es nicht wichtig, was in text[10] bis text[12] steht, es wird als ungültig betrachtet. Sie können text[] weiterhin mit der Zeichenmap aktualisieren, und dies sollte keine Objekte erstellen.

Ich hoffe, das hilft. Der obige Code ist nicht sehr robust, aber ich habe ihn mehr als Ausdruck der Ideen, die ich vermitteln möchte, geschrieben. Sie müssen Ihre eigenen Schleifen erstellen und die Daten innerhalb Ihres Codes ordnungsgemäß verwalten, aber dies umreißt die Mechanik dessen, was getan werden muss, um den Einsatz von Strings/StringBuilder/StringBuffer usw. zu vermeiden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X