2011-08-18 2 views
4

나는 내가 사용하고 엔진의 메소드 (andengine)가 way 매초마다 새로운 String 객체가 생성되고, 1 분 후에 GC 및 추가 AbstractStringBuilders 및 init에 의해 수집 할 59 개의 String 객체가 있습니다 ...문자열 및 쓰레기 수거

andeng의 부분 솔루션을 발견했습니다 이 같은 오프라인 포럼 :

private static StringBuilder mScoreValue = new StringBuilder("000000"); 

private static final char[] DIGITS = {'0','1','2','3','4','5','6','7','8','9'}; 

mScoreValue.setCharAt(0, DIGITS[(PlayerSystem.mScore% 1000000)/100000]); 
mScoreValue.setCharAt(1, DIGITS[(PlayerSystem.mScore% 100000)/10000]); 
mScoreValue.setCharAt(2, DIGITS[(PlayerSystem.mScore% 10000)/1000]); 
mScoreValue.setCharAt(3, DIGITS[(PlayerSystem.mScore% 1000)/100]); 
mScoreValue.setCharAt(4, DIGITS[(PlayerSystem.mScore% 100)/10]); 
mScoreValue.setCharAt(5, DIGITS[(PlayerSystem.mScore% 10)]); 
mScoreText.setText(mScoreValue.toString()); 

하지만 가장 큰 문제는,로 .toString 남아() 호출 할 때마다

이 문제를 해결하기 위해 어떤 방법이 있나요 새 개체를 반환?

+1

* 초당 하나의 String에 대해 정말로 염려합니까? 모든 클릭이나 다른 이벤트가 새로운 (이벤트) 객체를 생성하기를 기대하기 때문에 그다지 나에게는별로 좋지 않은 것 같습니다. –

+2

예. 보살 피지. 가비지 콜렉터는 충분히 빠르므로 초당 한 번에 할당하는 것에 대한 걱정은 완전히 놀랍도록 비례합니다. 그런 정신없는 사기극은 컴퓨터가 무엇을 가장 잘하는지입니다. 사람들이 그것을하고 더 많은 보람있는 당신의 지력을 사용하게하십시오. –

+0

해당 코드를 사용하면 심각한 조기 최적화의 경우가 될 수 있습니다. 최종적으로 모든 modulo 연산, divisions, 배열에서 가져 오기 및 StringBuilder의 문자 설정은 String 생성 및 관련 가비지 수집보다 처리량이 많을 것이라고 생각합니다. 그리고 다른 사람들이 지적한 것처럼, 결국에는 toString()을 사용하여 String을 생성합니다. 분당 60 개의 작은 오브젝트를 할당하는 것과 같은 한계를 가지고 작업하는 경우 Java는 어쨌든 사용하려는 언어가 아닙니다. C 또는 어셈블리가 거기에있는 마크에 더 가깝습니다. –

답변

3

내가 아는 한, Strings은 변하지 않으며 메서드가 String을 사용하면 매번 새로운 것을 만들어야합니다.

+0

글쎄요, 리플렉션을 사용하면 훨씬 더 높은 성능을 발휘할 수 있지만, 기본적으로는 그렇게됩니다. 그리고 1 초마다 1 작은 물체? 웃기지 않고 흥미 롭습니다. – Voo

+1

정말 큰 문제는 아니지만 양심적 프로그래머가 '걱정하지 말고 컴파일러가 처리하는 것'이 아니라 이러한 문제를 인식해야한다고 생각합니다. 그것은 당신의 기술에 대한 능력과 사랑에 대한 관심을 보여줍니다. –

+0

@Russ C 동의하지 않습니다. 모든 최적화에서 가장 중요한 것은 최선을 다해 이길 수있는 양을 파악하는 것입니다. <여기에 견적 견적 삽입>. 나는 그가 코드를 프로파일 링한다면 그가 그것을 알아 차리지 못할 것이라는 모든 생각을 할 것이다. 지옥에서 타이밍이 바뀌면 아무런 변화가 없을 것입니다. (그리고 적어도 javac에 대해 나는 문자열 연결을 위해 생성하는 코드를 정확히 알고있다. 루프 나 함수 호출이 없으면 거기에 좋은 규칙이 있다는 것을 잊어라.) – Voo

3

그것은 모두 StringBuilder 사용하는 좋은 후보가 같은 소리 :

http://developer.android.com/reference/java/lang/StringBuilder.html

또는 StringBuffer를 :

http://developer.android.com/reference/java/lang/StringBuffer.html

추론은 다음과 같습니다

StringBuffer를이 문자열을 저장하는 데 사용됩니다 그 변경됩니다 (String 객체는 변경할 수 없습니다). 필요에 따라 자동으로 확장됩니다. 관련 클래스 : String, CharSequence.

StringBuilder는 Java 5에서 추가되었습니다. 모든 점에서 동기화되지 않는다는 점을 제외하면 모든 점에서 StringBuffer와 동일합니다. 즉, 여러 스레드가 동시에 액세스하는 경우 문제가 발생할 수 있습니다. 단일 스레드 프로그램의 경우 가장 일반적인 경우인데 동기화 오버 헤드를 피하면 StringBuilder가 약간 더 빠릅니다.

편집 : 당신이 조심해야 할 한가지는 당신이 선택한 SB 등급을 어떻게 사용하는지입니다. 이

StringBuilder sb = new StringBuilder(score.ToString() + "hello, world!"); 

같은 사용이있는 경우 이유는 (너무 닷넷 동일)입니다 당신은 여전히 ​​2 개 문자열 CONCAT 운영, 당신은 아마도 거기에 실제로 3 문자열, score.ToString() 하나, 하나를 만들고있어있어 리터럴 "hello, world!"을 문자열로 변환하고 두 개가 함께 연결된 문자열로 변환합니다. 최상의 결과를 얻으려면 SB의 Append/insert/replace 메소드를 사용해야합니다.

+1

그들은 "+ int보다 빠르지 만 같은 수의 객체로 끝납니다. – SJuan76

+1

그는 여전히 새로운 문자열 객체를 생성하는'toString' 메소드를 호출해야하므로 문제는 여전히 존재합니다. – Daniel

+0

@ SJuan76'StringBuilder'는''StringBuilder'' 또는''StringBuffer'' 클래스를 생성하는 오버 헤드 때문에 "+"int보다 빠르지 않습니다. 그것들은 실제로 루프에서 몇 가지 미정의 문자열을 수정할 때만 유용합니다. – Daniel

2

처음에는 2 분에 120 개의 객체가 있습니다. 매우 큰 경우가 아니면 걱정할 필요가 없습니다.

둘째, String 클래스는 생성 된 모든 String 풀을 포함합니다. 그래서, 당신이 할 경우

String a = new String("Nabucodonosor King of Babilonia"); 
String b = new String("Nabucodonosor King of Babilonia"); 

Nabucodonosor King of Babilonia 메모리에 한 번만 저장된다 (그러나 그것을 가리키는 두 개의 String 객체가있다). 자세한 내용은 String # intern()을 참조하십시오.

마지막으로 Daniel이 지적했듯이 문자열이 변경되지 않으므로 문자열을 사용하는 해결 방법은 없습니다. 몇 가지 트릭 (이전 값으로 새 값을 확인하고 다른 경우에만 String을 작성)을 수행 할 수 있지만 추가 된 복잡성을 보완 할 수 있을지는 의문입니다.

+0

Interning을 언급 한 +1. –

관련 문제