12. juni 2006 - 10:26Der er
16 kommentarer og 1 løsning
sløv ændring ved mange modifikationer i string - gælder samme
...for int og double?
Jeg havde et problem tidligere hvor jeg ændrede indholdet i en String enormt meget. Tilsidst begyndte disse ændringer at være enormt tidskrævende, og jeg brugte så med succes en stringbuffer.
Mit spørgsmål er nu om samme problem gælder for int og double?
Det er mestendels når en streng bliver meget lang at den også bliver langsom at ændre. int og double værdier har en fast størrelse der aldrig ændrer sig.
Problemet med strenge er at de er immutable, hvilket betyder at der skal allokeres nyt hukommelse(Samt deallokere det gamle), hvilket er forholdsvis dyrt.
Dette gælder ikke for primitiver siden de kan ændre værdi.
1) overhead ved at new'e og gc'e objekter 2) overhead ved at flytte rundt på data fordi man ikke kan ændre data
#1 har alle reference typer (ikke simple data typer) #2 har alle immutable reference typer
#2 betyder kun noget ved store data mængder
derfor må det gælde at:
type overhead #1 overhead #2
simple typer intet intet int,double mutable ref typer medium intet StringBuilder immutable ref typer små data medium minimal Integer,Duble,kort String immutable ref typer stor data medium huge lang String
public class Objects { public static void main(String[] args) { int[] itest = { 10000000, 100000000, 1000000000 }; for(int n : itest) { (new TestIntegerObject(n)).test(); (new TestIntegerSimple(n)).test(); } int[] stestfixedsize = { 1000000, 10000000, 100000000 }; for(int n : stestfixedsize) { (new TestStringFixedSize(n)).test(); (new TestStringBuilderFixedSize(n)).test(); } int[] stestgrowing = { 100000, 1000000 }; for(int n : stestgrowing) { (new TestStringGrowing(n)).test(); (new TestStringBuilderGrowing(n)).test(); } } }
abstract class Test { private String name; protected int n; protected Object res; public Test(String name, int n) { this.name = name; this.n = n; } public void test() { long t1 = System.currentTimeMillis(); runtest(); long t2 = System.currentTimeMillis(); System.out.println(n + " " + name + " : " + (t2 - t1)); } public abstract void runtest(); }
class TestIntegerObject extends Test { public TestIntegerObject(int n) { super("Integer", n); } public void runtest() { Integer v = new Integer(0); for(int i = 0; i < n; i++) { v = v + 1; } res = v; } }
class TestIntegerSimple extends Test { public TestIntegerSimple(int n) { super("int", n); } public void runtest() { int v = 0; for(int i = 0; i < n; i++) { v = v + 1; } res = v; } }
class TestStringFixedSize extends Test { public TestStringFixedSize(int n) { super("String fixed size", n); } public void runtest() { String v = "*"; for(int i = 0; i < n; i++) { if(i % 2 == 0) { v = v + "*"; } else { v = v.substring(0, 1); } } res = v; } }
class TestStringBuilderFixedSize extends Test { public TestStringBuilderFixedSize(int n) { super("StringBuilder fixed size", n); } public void runtest() { StringBuilder v = new StringBuilder("*"); for(int i = 0; i < n; i++) { if(i % 2 == 0) { v.append("*"); } else { v.delete(1, 2); } } res = v; } }
class TestStringGrowing extends Test { public TestStringGrowing(int n) { super("String growing", n); } public void runtest() { String v = "*"; for(int i = 0; i < n; i++) { v = v + "*"; if(i % (n/100) == 0) { v = "*"; } } res = v; } }
class TestStringBuilderGrowing extends Test { public TestStringBuilderGrowing(int n) { super("StringBuilder growing", n); } public void runtest() { StringBuilder v = new StringBuilder("*"); for(int i = 0; i < n; i++) { v.append("*"); if(i % (n/100) == 0) { v = new StringBuilder("*"); } } res = v; } }
vi ser at både Integer og int er O(n) men at Integer tager ca. 6 gange så lang tid som int
forskellen er new og gc
vi ser at ved korte strenge af fast længde er både String og StringBuilder O(n), men at String tager ca. 3 gange så lang tid som StringBuilder
forskellen er new og gc
vi ser at ved lange strenge hvor længden er proportional med antal operationer (realistisk i mange situationer) så er StringBuilder O(n) men String er O(n*n)
overhead ved kopiering af data for String overskygger totalt effekten af new og gc
iøvrigt mener jeg at effekten af StringBuilder versus String tit overvurderes
det er meget vigtigt ved meget store strenge men i 98% af tilfældene i praktisk kode betyder det ikke noget fordi strengene er små og det ikke laves alt for mange gange
men eksempelt nævnes næsten altid som det første når man snakker optimering af kode, så alle kender det
Mht StringBuilder bliver den brugt til en rimelig god lang streng hvor jeg hele tiden byggede videre på den, så der er en giga effekt (testede det tidligere).
Men dejlig information med de andre typer.
Tak til alle - point til arne for det gode eksempel.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.