[Java] code optimalisatie

Pagina: 1 2 Laatste
Acties:
  • 872 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Een vraag voor de java kenners onder de GOT bezoekers: Welke optimalisaties zijn aan te raden als je programmeert voor snelheid?

Ik ben al een paar dagen aan het googlen, maar vind eigenlijk alleen zaken die niet echt up-to-date zijn. We zitten inmiddels aan JRE 1.4.x;

Wie heeft er wat recente links/artikelen, of zelf tips?

Bij voorbaat dank.

Acties:
  • 0 Henk 'm!

  • Postman
  • Registratie: Februari 2000
  • Laatst online: 06-04 13:49
Zoals deze (zeer magere) search op java.sun.com toont: gebruik geen variabelen die je niet gebruikt en ook geen methodes die je niet gebruikt.

En wat voor optimalisatie zoek je eigenlijk? Snelheid, of code overdraagbaarheid?

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
flamerx: snelheid. Het gaat om een app die veel gegevens verwerkt.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
als je met strings werkt altijd StringBuffers gebruiken. en ik neem aan dat werken met pure java arrays [] ook sneller is dan met Vectors/etc etc... en gebruik van 'pure' types... (int, boolean, euh).

Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
1) Beginnen met je algoritmes te optimaliseren. Dat levert (vaak) veel tijd op
2) Pak alleen code aan die vaak wordt aangeroepen.
3) Werk met java.nio voor input/output

[meer kan ik ff niet opkomen]

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik gebruik bijvoorbeeld een Socket voor een verbinding met een lokale SMTP server. Ik verzend 10 mails, dan een disconnect, en een nieuwe connect.

Het verzenden van de mails gaat zeer snel, maar het lezen van de reacties van de SMTP server duurt veel te lang. Ik gebruik(te) hiervoor een BufferedReader om de een InputStreamReader, die om de inputstream van de socket zit.

Ter illustratie: ik heb een app geschreven die gepersonaliseerde e-mail genereerd, in java. Op een dual machine zit ik inmiddels aan zo'n 20ms per gegenereerd bericht (vanaf het krijgen van de opdracht, tot en met het verzenden naar de SMTP server). Het gaat veelal om berichten rond de 20 kilobyte.

Dit lijkt me echter nog vrij traag.

Ik ben al eerder aan het optimaliseren gegaan, en vond toen een veel snellere methode om een replace in een grote string te doen, die een factor 4-8 sneller is dan de standaard String.replace():
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static String replace(String orig, String from, String to)
    {
        int fromLength = from.length();
        
        if (fromLength==0)
            throw new IllegalArgumentException 
            ("String to be replaced must not be empty");
        
        int start = orig.indexOf (from);
        if (start==-1)
            return orig;
        if(from.equals(to)) return orig;
        
        boolean greaterLength = (to.length() >= fromLength);
        
        StringBuffer buffer;
        // If the "to" parameter is longer than (or
        // as long as) "from", the final length will
        // be at least as large
        if (greaterLength)
        {
            buffer = new StringBuffer(orig.length());
        }
        else
        {
            buffer = new StringBuffer();
        }
        
        char [] origChars = orig.toCharArray();
        
        int copyFrom=0;
        while (start != -1)
        {
            buffer.append (origChars, copyFrom, start-copyFrom);
            buffer.append (to);
            copyFrom=start+fromLength;
            start = orig.indexOf (from, copyFrom);
        }
        buffer.append (origChars, copyFrom, origChars.length-copyFrom);
        
        return buffer.toString();
    }

Acties:
  • 0 Henk 'm!

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Gebruik
code:
1
java -Xrunhprof:file=java.opt.txt
Je krijgt dan een lijstje met alle methodes die in je progsel worden gebruikt plus een percentage van het geheel. Deze kun je dan gebruiken om te optimaliseren.

Pak de bovenste 5 van die lijst en ga die optimaliseren.

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Acties:
  • 0 Henk 'm!

Anoniem: 64569

Uhm iets replacen in een String kan nog wel sneller denk ik:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    public static String replaceUltrasnel(String source, String firstString, String newString)
    {
        return replaceUltrasnel(new StringBuffer(source), firstString, newString).toString();
    }

    public static StringBuffer replaceUltrasnel(StringBuffer source,  String firstString, String newString)
    {
        final int firstStringLength = firstString.length();
        final int newStringLength = newString.length();
        final char[] firstChars = firstString.toCharArray();
        final char[] newChars = newString.toCharArray();

        if(firstString.length() == newString.length())
        {
            int max = source.length() - firstStringLength;
            boolean equals = false;

            for(int i=0; i < max; i++)
            {
                equals = true;

                for(int j=0; j < firstStringLength; j++)
                {
                    if(source.charAt(i + j) != firstChars[j])
                    {
                        equals = false;
                        break;
                    }
                }

                if(equals)
                {
                    for(int j=0; j < firstStringLength; j++)
                    {
                        source.setCharAt(i + j, newChars[j]);
                    }
                    i += firstStringLength - 1;
                }
            }
        }
        else
        {
            int max = source.length() - firstString.length() + 1;
            int dif = newString.length() - firstStringLength;
            boolean equals = false;

            for(int i=0; i < max; i++)
            {
                equals = true;
                for(int j=0; j < firstStringLength; j++)
                {
                    if(source.charAt(i + j) != firstChars[j])
                    {
                        equals = false;
                        break;
                    }
                }

                if(equals)
                {
                    source.replace(i, i + firstStringLength, newString);
                    i = i + newStringLength - 1;
                    max = max + dif;
                }
            }
        }

        return source;
    }


Ik geloof: © by mbravenboer (dus geen eer voor mij :) )

Acties:
  • 0 Henk 'm!

  • pasz
  • Registratie: Februari 2000
  • Laatst online: 27-04 00:27
Geen java gebruiken :)
Maar een taal die geen gebruik maakt van een virtual machine

woei!


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
proper - met dat oog voor detail kun je evengoed zonder StringBuffer werken maar zelf met een char[] array werken :) kun je ook System.ArrayCopy gebruiken...

maar als je steeds hetzelfde moet doorsturen behalve een paar velden zijn er wel betere technieken - denk aan een parsed template bijvoorbeeld. ik neem aan dat je ergens

beste {PERSON} ,

we willen...

en dan doe je voor elk bericht een Replace? kun je VEEL beter gewoon je originele template effe opdelen (dus 1 x 'replace' (of gewoon zoekem)

krijg je een Vector mParts... dan hou je ook bij welke indexes fields zijn en die stop je dan weer in een HashMap en die vul je dan in voor elke message dan regeneer je alles met simple 'appends'... (je kan dan ook ineens de length berekenen - on the fly ) dus zal je nooit een memory copy krijgen...

een element van de hashMap is bijvoorbeeld

class hashObject
{
int mVectorID;
String mValue
}

dan 'Hash' je elk 'Field' (ie een {}) mHash.put("fieldname-x", new hashField(indexInVector, "");

dan voor elke nieuwe param: doe je een mHash.get("fieldName").mValue = hello


dan stop je de values in je Vector.. (ArrayList)

en dan een for(each Element in Vector) myStringBuffer.append(aVectorElement)...

hmm zoals je ziet is dat dus een ander 'algoritme'

Quick reply is echt te klein voor zo'n posts :)

edit:

dennis62.. heb toch nog een paar dingetjes die de replacen nog wel kunnen versnellen.... :)

[ Voor 8% gewijzigd door hobbit_be op 04-03-2003 21:59 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: de kneep zit hem er nu net in, dat er een zeer grote varieteit aan berichten is. Vandaar dat ik niet kan optimaliseren aan de content kant.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
nou ben ik vroeger asm coder geweest dus die replace vond ik wel een leuk 'avond' probleempje. :) vooral omdat een replace voor iedereen handig is.

voorlopig heb ik alleen het geval dat de nieuwe string.length == old string.length.
eens onder handen genomen. Reden was natuurlijk om te zien of ik mbravenboer code kon verbeteren, waarvan ik in de afgelopen weken veel hulp van heb gehad.

_/-\_o

nu heb ik dus dat eerste deel onder handen genomen en ik kom tot een resultaat dat zowat 300% sneller is. Ik heb het getest met verschillende replace sizen en verschillende grootte van text met elke test minimum 10000 samples. Natuurlijk is dit op een Celeron 400Mhz dus weet ik niet wat het geeft op andere CPU's.

Alleen als de searchtext groter word (1MegaCharacters) dan wordt het verschil kleiner. Zelfs een keer was het trager maar dat heb ik niet kunnen herhalen (background process?), maar voor de rest is het zeer stabiel.

Ik ga er nog wat speciale gevallen insteken want ik vermoed dat een System.arraycopy op een bepaald punt trager is dan een gewone setChar...

Morgen probeer ik de verschillende sizes, ik vermoed dat het verschil nog groter kan zijn maar echt zeker ben ik niet (hangt af van hoe goed System.arraycopy is).

Moet zeggen heb ervan genoten om in de 'underbelly' van Java (zover er een is) te knoeine en is geen SWing-geklooi :)...

hier is de code voor het eerste deel:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//dit is overigens nog een foute in Denis62/mbravenboers code die +1 moet
//er wel staan anders wordt een string op het einde niet replaced...
  final int tMaxIndex = source.length() - tNewStringLength + 1;
  char[] tBuffer = source.toCharArray(); //ik geef geen stringbuffer door maar een
                                                              //gewone string..
  int tIndex = 0; //index
  int tSearchIndex; //to prevent reinit of int var in case java doesn't see it..

  nextChar:while (tIndex < tMaxIndex) 
  {
      tSearchIndex = 0; //restart search
      while (tSearchIndex < tNewStringLength)
      {
          if (tBuffer[tIndex++] != tOld[tSearchIndex++]) 
          {
             continue nextChar;
          }
       }
       //if we are here it means we found a match 
       System.arraycopy(tNew, 0, tBuffer, tIndex - tNewStringLength,
                                    newStringLength);
   }
   return new String(tBuffer); 

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
B-Man schreef op 05 maart 2003 @ 00:41:
hobbit_be: de kneep zit hem er nu net in, dat er een zeer grote varieteit aan berichten is. Vandaar dat ik niet kan optimaliseren aan de content kant.
dat begrijp ik best maar ik heb ook begrepen dat je toch een soort standaard bericht hebt dat je x keer moet opsturen. Dat je elk type bericht moet parsen is duidelijk maar met die parsed template moet je slechts 1 keer zoeken waar
de fields nu zitten.

stel dat je op 1 bericht (bijvoorbeeld 2000 characters) 10 dingen moet veranderen
dat is dus 10 keer een replace (als je weet dat iets maar 1 keer kan voorkomen kun je er natuurlijk een conditie opdoen) maar toch. Doe dit voor 20 klanten dan zit je al aan zo'n 200 replaces... met een parsed (per type bericht) ga je 1 keer zoeken en voor de rest is het toch een ZEER snelle opeenvolging van SB.append()..
(en zoals al gezegd kun je tijdens het invullen van de data al berekenen hoe groot
de final gaat zijn dus word de append() wel heel erg efficient)...

ik gebruik die techniek in PHP waar ik ik templates invul met data van XML-queries , en alhoewel de XML-query veel tijd in beslag neemt ging er toch een pak tijd af. en PHP is heel wat sneller met Strings... (om nog maar te zwijgen over pure C/C++)

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: leuk om te zien dat je er wat tijd in gestoken hebt!

Ik zit zelf echter, naast variabele content, ook met het feit dat ik bepaalde "tags" (zoals [voornaam]), per e-mail vervang door data uit een database. De tekst die de tag vervangt is dus vrijwel iedere keer een andere lengte dan de tag zelf.

Ik gebruik nu voor simpele tags de replace functie die ik eerder postte, en gebruik daarnaast ook nog java.util.regex voor een aantal complexere tags. Dat brengt me overigens meteen op een andere vraag: weet een van jullie welke regex library het snelste is? Ik gebruik op dit moment dus java.util.regex, maar mogelijk zijn alternatieven zoals de GNU lib sneller?

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be schreef op 05 maart 2003 @ 01:08:
[...]

dat begrijp ik best maar ik heb ook begrepen dat je toch een soort standaard bericht hebt dat je x keer moet opsturen. Dat je elk type bericht moet parsen is duidelijk maar met die parsed template moet je slechts 1 keer zoeken waar
de fields nu zitten.

stel dat je op 1 bericht (bijvoorbeeld 2000 characters) 10 dingen moet veranderen
dat is dus 10 keer een replace (als je weet dat iets maar 1 keer kan voorkomen kun je er natuurlijk een conditie opdoen) maar toch. Doe dit voor 20 klanten dan zit je al aan zo'n 200 replaces... met een parsed (per type bericht) ga je 1 keer zoeken en voor de rest is het toch een ZEER snelle opeenvolging van SB.append()..
(en zoals al gezegd kun je tijdens het invullen van de data al berekenen hoe groot
de final gaat zijn dus word de append() wel heel erg efficient)...

ik gebruik die techniek in PHP waar ik ik templates invul met data van XML-queries , en alhoewel de XML-query veel tijd in beslag neemt ging er toch een pak tijd af. en PHP is heel wat sneller met Strings... (om nog maar te zwijgen over pure C/C++)
Ik cache max 30 seconden een blok content, om te voorkomen dat ik onnodig veel de database induik. Ik ga morgen eens kijken of ik een oplossing kan maken die een blok content vertaalt naar een template die ik direct kan gebruiken m.b.v. een StringBuffer.

Of dit echter efficient is, weet ik niet. Het komt ik de praktijk namelijk veel voor dat er binnen de seconde verschillende (>10) content blokken nodig zijn, en de seconde erna weer andere blokken. Of de "overhead" van het vertalen van het content-blok naar een bruikbaar formaat opweegt tegen de mogelijke snelheidswinst bij het genereren van een bericht, ontdek ik snel zat!

In ieder geval bedankt voor het meedenken!

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
nou - effe een late niter - tis nu 4:22am :)

maar ik me nu effe een replace die enorm veel sneller is... hoe enorm ben ik zelf
verrast van. :) euh de verschillen op grote text waarvan er een hoop echte replacen hangt is het verschil wel erg groot.

(per 72x zijn er 3 replaces)

72000 characters / test:100 (zijn dus 100x1000x3 replaces = 3.000.000)
ooString :2.578s 2 seconden
mBravenBoer :136.297s 2 minuten

toegegeven een replace op een document met 72000 zul je niet
vaak tegenkomen... door de enorme memory copies valt
stringbuffer uit de boot.

maar ook op kleinere is er een groot verschil. In neem aan
dat enkel bij een single replace er weinig verschil zal zijn.
edit: effe getest met een sample van 1.000.000 maar ook hier
is het verschil ongeveer x2.5... (niet dat je daar iets van zou merken)


720 characters / test:10000
0.985s - per keer is dat dus 0.09ms
3.453s x3 - per keer 0.35ms

7200 characters / test:1000
0.969s - per keer is dat dus 1ms
8.078s x8 - 8ms

ooh en dit is wanneer de de nieuwe tekst > oude tekst...

voor dezelfde monster replace maar dan nieuwe tekst < oude tekst:

ooString :1.296s //relatief dus ook een pak sneller...
mBravenBoer :110.391s

en ja ik test de correctheid v/d results ;)...

code release ik morgen wel omdat ie nog niet snel genoeg is :)

[ Voor 6% gewijzigd door hobbit_be op 05-03-2003 04:48 ]


Acties:
  • 0 Henk 'm!

  • esf
  • Registratie: Juni 2002
  • Laatst online: 21-02 08:56

esf

- Geen threads gebruiken : synchronisatie kost veel tijd
- Beperk het aantal methode aanroepen : Gebruik voor methoden die maar vanuit 1 deel (of weinig) van de code aangeroepen worden geen methoden maar plak de code gewoon naar de plek waar je de methodeaanroep wilde doen. Het springen van methode naar methode kost tijd
- Als je veel berekeningen doet kun je dynamisch programmeren: sla alle tussenresultaten op en gebruik ze als je ze weer nodig hebt. Verhoogt space complexiteit maar verlaagt de tijdcomplexiteit van je programma

The hardest thing in the world to understand is the income tax. - Albert Einstein


Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Bij talen als Java zit het belangrijkste probleem in object creatie. Objecten creeeren en weer opruimen is duur. In het algemeen kan je daar dus allereerst naar kijken als je op een bepaald punt performance problemen hebt.

Daarnaast zijn er natuurlijk erg veel kleine praktische zaken die hier al een paar keer genoemd zijn. In principe komen deze echter vaak weer terug op de object creatie. Het String/StringBuffer verhaal heeft hier ook gewoon mee te maken. Het belangrijkste probleem is dat de object creatie daar niet zo zichtbaar is.

Verder zou ik goed kijken waar nu echt het probleem zit voordat je je code echt gaat verpesten. Ik zie hier enkele tips staan die code echt een stuk minder aantrekkelijk maken. Die moet je dus alleen maar toepassen als je echt weet dat daar het probleem zit.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

De belangrijkste dingen zijn al genoemd:

1. identificeren waar de bottleneck zit
2. Object creatie
3. Objecten handmatig "nullen" om je Garbage Collector te ontzien
4. Zware berekeningen cachen in opzoektabellen

Verder hangt de mogelijke optimalistie erg van het stuk code af. En je hebt natuurlijk altijd de afweging tussen snel genoeg en snelst. Als je geen performance probleem hebt hoef je ook niets te optimaliseren

Acties:
  • 0 Henk 'm!

Anoniem: 49627

ook is even een poging gewaagt, hij print de tijd naar buiten dat hij gemiddeld nodig had per replace actie. Bij mij op een celeron 466 was dat 0.011515
milliseconde
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Test {
  private static StringBuffer buffer;

  public static void main(String[] args) {
    int tries = 200000;
    long start = System.currentTimeMillis();
    for (int i = 0; i < tries; ++i)
      replace("Even een complete zin", "complete", "nieuwe");
    System.out.println(((double)(System.currentTimeMillis()-start))/ (double)tries);
  }  

  public static String replace(String replacable, String oldRegion, String newRegion){
    int oldRegionLength = oldRegion.length();
    int newRegionLength = newRegion.length();
    int replaceStart = replacable.indexOf(oldRegion);
    int replaceEnd = oldRegionLength + replaceStart;

    int bufferLength = newRegionLength + (replacable.length() - oldRegionLength);
    if (buffer == null)
      buffer = new StringBuffer(bufferLength);
    else
      buffer.setLength(bufferLength);

    int i = 0;
    for (; i < replaceStart; ++i)
      buffer.insert(i, replacable.charAt(i));

    buffer.insert(i, newRegion);
    i = i + newRegionLength;
    buffer.insert(i, replacable.substring(replaceEnd));

    return buffer.toString();
  }
}

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 13-05 17:10
Natuurlijk is zo hier en daar de code flink te optimaliseren, maar onthoud wel dat java nou niet echt snel is. Als je iets gaat bouwen wat echt snel moet zijn kun je beter gewoonweg een andere taal pakken. C++ oid... :)

Acties:
  • 0 Henk 'm!

Anoniem: 49627

Maar ik zie al dat die van mbravenboer sneller is...

Acties:
  • 0 Henk 'm!

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Marcj schreef op 05 March 2003 @ 10:48:
Natuurlijk is zo hier en daar de code flink te optimaliseren, maar onthoud wel dat java nou niet echt snel is. Als je iets gaat bouwen wat echt snel moet zijn kun je beter gewoonweg een andere taal pakken. C++ oid... :)
Helaas heb je dit niet onderbouwd met benchmarks oid

De "traagheid" van Java ligt er niet aan dat het ge-interpreteerd wordt. Door de Just-in-time compiler wordt de code namelijk native gecompileerd. De grote vertraging is het laden van Objecten. En dat probleem heb je ook in C++. En is dus afhankelijk van de programmeur.

Java zal wanneer het juist geprogrammeerd is en er geen GUI gebruikt wordt nagenoeg evensnel zijn als een C++ applicatie.

Real-time applicaties is een ander verhaal natuurlijk.

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
markvleth: Maar ik zie al dat die van mbravenboer sneller is...
Dat stukje code was het resultaat van een nachtelijke wedstrijd hier in P&W om de snelste replacer te maken. Het topic is denk ik nog wel makkelijk te vinden. Het is wel aardig om te zien hoe de snelheid steeds verder verbeterde.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 13-05 17:10
wasigh schreef op 05 maart 2003 @ 11:00:
[...]

Helaas heb je dit niet onderbouwd met benchmarks oid

De "traagheid" van Java ligt er niet aan dat het ge-interpreteerd wordt. Door de Just-in-time compiler wordt de code namelijk native gecompileerd. De grote vertraging is het laden van Objecten. En dat probleem heb je ook in C++. En is dus afhankelijk van de programmeur.

Java zal wanneer het juist geprogrammeerd is en er geen GUI gebruikt wordt nagenoeg evensnel zijn als een C++ applicatie.

Real-time applicaties is een ander verhaal natuurlijk.
Interpertatie vertraagd de boel natuurlijk wel. Plus dat java platformonafhankelijk moet zijn kan het niet altijd gebruik maken van optimalisaties. Iets van met C wel kan. Ik heb C++ ook alleen maar als voorbeeld genomen.
Een ander probleem waar ik met java regelmatig tegen aanloop is het geheugengebruik. Als je dingen als een JEditorPane gaat gebruiken schiet het geheugengebruik echt gigantisch omhoog. Swing is zowiezo traag wat dat betreft. Kun je beter AWT gebruiken, hoewel dat ook weer z'n nadelen heeft.
Wat ik probeer te zeggen dat voor iets waar echt performance voor nodig is je volgens mij (en volgens de docenten die mij Java leren :P) beter geen java kan gaan gebruiken. Java is goed voor programmeurs-efficiëntie, om het zo maar te noemen.

Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
mbravenboer schreef op 05 March 2003 @ 11:06:
Dat stukje code was het resultaat van een nachtelijke wedstrijd hier in P&W om de snelste replacer te maken. Het topic is denk ik nog wel makkelijk te vinden. Het is wel aardig om te zien hoe de snelheid steeds verder verbeterde.


Leukste was nog wel dat .oisyn verloor met z'n C++ converted to Java code :P :+

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-05 12:26

Janoz

Moderator Devschuur®

!litemod

esf schreef op 05 March 2003 @ 08:54:
- Geen threads gebruiken : synchronisatie kost veel tijd
......


Waneer je (zoals in dit geval met de sockets) erg afhankelijk bent van trage IO is het juist wel van belang om threads te gebruiken. Terwijl 1 thread aan het wachten is tot de buffer van de socket weer leeg is kan een andere thread rustig wat nieuwe mails genereren.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Marcj: Interpertatie vertraagd de boel natuurlijk wel. Plus dat java platformonafhankelijk moet zijn kan het niet altijd gebruik maken van optimalisaties. Iets van met C wel kan.
De programmeur die in Java werkt kan geen creepy constructies gebruiken om code te optimaliseren. Dat betekent echter niet dat er geen platform (processor) specifieke optimalisaties gebruikt kunnen worden. De JVM implementatie zelf is namelijk helemaal niet platform onafhankelijk (er wordt immers een nieuw platform gecreeerd) en kan gewoon gebruik maken van platform specifieke features. Dit betekent bijvoorbeeld dat je nog steeds een hele goede JITter kan schrijven voor een specifieke processor architectuur.
Swing/AWT
Je moet de archictuur van een systeem als Java of .NET niet beoordelen via de brakke implementaties van GUI libraries. Je beoordeelt dan de GUI library en niet het platform. Wellicht zegt het wel iets als het kennelijk lastig is om een goede GUI library (of andere typisch platform specifieke zaken) te schrijven.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

Anoniem: 49627

Tijd voor nieuwe docenten zou ik zeggen Marcj.

Een hoop is afhankelijk van de programmeur. Zoals bijvoorbeeld hierboven, de code van mbravenboer is sneller als die van mij. Dus die ruimte is er gewoon. En als je gaat kijken naar bijvoorbeeld EJB's zit performance zeker wel goed. Daar wordt immers gebruik gemaakt van caching van objecten, dus van elke Bean contiainer is maar 1 instantie (net zoals een servlet). En dat is gewoon een vergelijkbare snelheid met C, al dan niet sneller...

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 13-05 17:10
Beide helemaal gelijk hoor :)
Maar ik vindt het toch wel een probleem dat er niet echt een goede GUI bij Java zit. C++ is voor mij ook al even geleden (ik doe voor m'n studie alleen nog maar Java), maar daarin moet dit toch iig een stukje sneller kunnen.
Je gaat natuurlijk niet even snel zoiets schrijven voor java. OO-talen zijn toch juist gemaakt voor het hergebruik van code. En de standaard code die bij de J2SDK zit is niet altijd even snel. Dat zie je maar weer in het bovenstaande voorbeeld.

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Marcj: Beide helemaal gelijk hoor :)
Dat lucht op :D .
Maar ik vindt het toch wel een probleem dat er niet echt een goede GUI bij Java zit.
Niet "bij" Java, maar wel goed: SWT en JFace.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

Anoniem: 49627

Maar ik vindt het toch wel een probleem dat er niet echt een goede GUI bij Java zit.
Java is een van de winige talen met lightweight componenten. Dus het is een luxe dat het er is. Een interface is platform afhankelijk en c++ heeft geen interface alleen maar wrappers (zoals bijvoorbeeld borland VCL)

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 13-05 17:10
Anoniem: 49627 schreef op 05 maart 2003 @ 11:40:
[...]

Java is een van de winige talen met lightweight componenten. Dus het is een luxe dat het er is. Een interface is platform afhankelijk en c++ heeft geen interface alleen maar wrappers (zoals bijvoorbeeld borland VCL)
Dat snap ik zelf ook wel. Maar zelfs de coders van Sun zelf hebben gezegt dat Swing niet echt goed in elkaar zit. Het is gewoon traag.
Desondankt gebruik ik het wel, omdat het er altijd hetzelfde uit ziet. Je moet er gewoon niet al te ingewikkelde dingen mee doen.

Heeft iemand bijvoorbeeld al eens Borland Together 6.0 gebruikt? Om in java programma's te gaan ontwerpen etc.. Die interface is ook niet echt snel moet ik zeggen ;)
mbravenboer schreef op 05 maart 2003 @ 11:35:
Niet "bij" Java, maar wel goed: SWT en JFace.
Dit wil ik wel eens gaan proberen. Heb je ook zo een link? Als ik bij google zoek op JFace, kom ik uit bij Eclipse..

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Marcj: Dit wil ik wel eens gaan proberen. Heb je ook zo een link? Als ik bij google zoek op JFace, kom ik uit bij Eclipse..
Het is inderdaad onderdeel van Eclipse, alhoewel er alleen een afhankelijkheid van Eclipse naar SWT/JFace is, niet andersom. Helaas heeft nog steeds niemand de moeite genomen om een aparte SWT/JFace SDK te maken. Er zijn echter al wel applicaties die het los van Eclipse gebruiken.

Omdat SWT/JFace volledig open source is (met name ook de native, platform specifieke code), is het mogelijk om een native compiler te gebruiken om SWT gebaseeerde Java GUI applicaties te compileren.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 14-04 17:27
wasigh schreef op 05 March 2003 @ 11:00:
De "traagheid" van Java ligt er niet aan dat het ge-interpreteerd wordt. Door de Just-in-time compiler wordt de code namelijk native gecompileerd. De grote vertraging is het laden van Objecten. En dat probleem heb je ook in C++. En is dus afhankelijk van de programmeur.

Java zal wanneer het juist geprogrammeerd is en er geen GUI gebruikt wordt nagenoeg evensnel zijn als een C++ applicatie.
Eh, pardon?
C++ laadt geen objecten, hoor, hooguit DLLs. Evengoed zijn de meeste functie calls module-local, dus de linker kan whole-program (ok, whole-module) optimasatie doen. VC7 doet dat bijvb. al.

De garbage collectie zal ook een groot snelheidsverschil kunnen veroorzeken. Meestal valt dat in het nadeel uit van Java.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Marcj schreef op 05 March 2003 @ 11:09:
[...]

Interpertatie vertraagd de boel natuurlijk wel. Plus dat java platformonafhankelijk moet zijn kan het niet altijd gebruik maken van optimalisaties. Iets van met C wel kan. Ik heb C++ ook alleen maar als voorbeeld genomen.
Een ander probleem waar ik met java regelmatig tegen aanloop is het geheugengebruik. Als je dingen als een JEditorPane gaat gebruiken schiet het geheugengebruik echt gigantisch omhoog.
Swing is zowiezo traag wat dat betreft. Kun je beter AWT gebruiken, hoewel dat ook weer z'n nadelen heeft.
Ik zei al dat niet naar SWING/AWT moet kijken. Deze zijn idd traag maar zoals gezegd wil dat niet zeggen dat Java traag is :)
Wat ik probeer te zeggen dat voor iets waar echt performance voor nodig is je volgens mij (en volgens de docenten die mij Java leren :P) beter geen java kan gaan gebruiken. Java is goed voor programmeurs-efficiëntie, om het zo maar te noemen.
Je moet niet alles geloven wat je docenten zeggen. meesatl hebben ze dit soort dingen ook alleen maar gehoord praten ze mensen na zonder dat het zelf getest hebben.

Wat ik al zei: voor real-time applicaties zoals een noodstop op een machine oid moet je geen Java gebruiken. Voor andere zaken kan het zeker en zal het performance verschil met bijvoorbeeld C++ minimaal zijn. Zeker als de java-programmeur zijn vak verstaat en goede code kan schrijven.

Mensen die beweren dat het onmogelijk is om in Java snelle code te schrijven kunnen niet goed java programmeren ;)

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
MSalters: C++ laadt geen objecten, hoor, hooguit DLLs.
Ik denk dat wasigh een beetje slecht uitdrukte dat er sowieso al een overhead is bij heap gealloceerde objecten.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

MSalters schreef op 05 maart 2003 @ 12:30:
[...]

Eh, pardon?
C++ laadt geen objecten, hoor, hooguit DLLs. Evengoed zijn de meeste functie calls module-local, dus de linker kan whole-program (ok, whole-module) optimasatie doen. VC7 doet dat bijvb. al.

De garbage collectie zal ook een groot snelheidsverschil kunnen veroorzeken. Meestal valt dat in het nadeel uit van Java.
Volgens mij moet je in C++ wanneer je gebruik maakt van objecten, geheugen alloceren op de heap en dat kost tijd.

De garbage collector draait als een low-priority thread op de achtergrond. Het vraagt alleen een hogere prioriteit wanneer er ineens veel objecten opgeruimd dienen te worden. En er dienen alleen veel objecten opgeruimd te worden als ze door de programmeur niet goed "voor" opgeruimd zijn

Acties:
  • 0 Henk 'm!

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

mbravenboer schreef op 05 March 2003 @ 12:33:
[...]

Ik denk dat wasigh een beetje slecht uitdrukte dat er sowieso al een overhead is bij heap gealloceerde objecten.
Het was idd misschien een beetje kort door de bocht ;)

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
nog effe verder met die replace :) ben natuurlijk al effe gaan kijken op die oude topic (had ik het eerder geweten:). Mijn strategy was ongeveer als die van Zynt - maar hier en daar wat special cases en kleinere match search leidt dan nog tot een increase van zo rond de 75%.

als de originele string die je meegeeft veranderd mag worden is er nog snelheids winst te boeken. het nadeel is dat de code 240 regels is :) dus die ga ik hier niet posten maar wel op request. Maar het idee is hetzelfde als die van Zynth... gewoon beter 'new' managment en special cases.

ivm GUI optimilisatie is SWT idd wel zalig maar omdat ie 'hard' is ook een pak minder cross-platform. Bovendien wordt SWT niet officieel ondersteunt door Sun: Swing or DIE :). Ik gebruik JBuilder en die is ook met Swing in elkaar geknokt en echt 'traag'-traag vind ik em niet, niet te vergelijken met Native GUI maar toch niet zo-slecht. Misschien zou iemand een FlashMX front-end moeten schrijven met Java2D. en als je wil kun je natuurlijk ook nog gaan OpenGL-en :). Bestaat er eigenlijk een Java VM -> CIL ?

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Java VM -> CIL ?
Het probleem is daarbij met name de libraries, niet de bytecode. Microsoft heeft het zelf gedaan met 1.1 libraries, J# en wat conversie tools, maar dat schiet praktisch gezien niet zo op.

Dit is ook wel aardig:
http://radio.weblogs.com/0109845/

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
hobbit_be: ivm GUI optimilisatie is SWT idd wel zalig maar omdat ie 'hard' is ook een pak minder cross-platform.
Tja, iets wat platform specifiek is kan je nu eenmaal niet platform onafhankelijk implementeren :+ .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
wel SWT is toch een 'beetje' independent (Win98, Linux, ... apple later). :) Wat ik eigenlijk gek vind: alle GUI's werken met een windowig systeem : dus pure lege windows ,
en verder een paar snelle DrawRoutines. Als ze die nou eens abstractifying dan heb je toch het beste van beide werelden? Snelheid + Crossplatform + same look. Swing is beginnen met 'niets' en SWT begint met het einde - hebben vast de leer van de Buddha nooit tegengekomen :)

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
hobbit_be: wel SWT is toch een 'beetje' independent (Win98, Linux, ... apple later). :)
Uiteraard, maar er is wel per platform native code nodig. Net zoals je met een Java VM een nieuw platform creeert wat dan platform onafhankelheid wordt genoemd, creeer je met SWT een nieuwe GUI library die dan ook platform onafhankelijk genoemd kan worden...
Als ze die nou eens abstractifying dan heb je toch het beste van beide werelden?
Je bedoelt dat iedereen over de hele wereld het eens wordt? :+ .
Snelheid + Crossplatform + same look.
Tja, dat same look is juist het probleem. Windows XP gebruikers zijn niet geinteresseerd in een standaard Java look, ze willen dat de Java applicatie gewoon de skin gebruikt die zij hebben ingesteld. Hetzelfde voor Mac OS X: dat moet er gewoon uit zijn als een Aqua applicatie. Apple heeft met hun Swing look and feel laten zien dat dit ook inderdaad mogelijk is op basis van Swing. Nu moet alleen nog iemand de investering aandurven om datzelfde voor Microsoft Windows te gaan doen.
Swing is beginnen met 'niets' en SWT begint met het einde
SWT kan ook terugvallen op getekende componenten. Het is dus in feite een tussenweg tussen AWT en Swing.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Haha, we hadden het over Java in het algemeen, en nu gaat het richting een GUI topic...

Terug ontopic... Ik heb zojuist mijn app uitgebreid met een nieuwe module voor de verwerking van content. Bij het laden van content gebruik in nu onderstaande functie om de text te verdelen in strings en tags:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
public static ArrayList parseText(String text) {
        
        ArrayList list = new ArrayList();
        Tag tag;

        if(text.indexOf("[") == -1) {
            // Return a one-value ArrayList
            list.add(text);
            return list;
        }
        
        char []input = text.toCharArray();
        int i = 0, length = input.length, tagStart = -1, tagEnd = -1;
                
        for(;i<length;i++) {
            // find "["
            if(input[i] == '[') { 
                tagStart = i; 
                
                // If we have a tagEnd < this tagStart, append the diff WORKS
                if(tagEnd != -1 && tagStart > tagEnd) {
                    char []txt = new char[tagStart-tagEnd-1];
                    System.arraycopy(input, tagEnd+1, txt, 0, tagStart-tagEnd-1);
                    list.add(String.valueOf(txt));
                }
                // Text before the first tag WORKS
                if(tagEnd == -1 && tagStart > 0) {
                    char []txt = new char[tagStart];
                    System.arraycopy(input, 0, txt, 0, tagStart);
                    list.add(String.valueOf(txt));
                }
                
                continue; 
            }
            
            // Now look for the first space, or "]"
            if(tagStart != -1) {
                if(input[i] == ']') {
                    tagEnd = i;
                    
                    // Create a new Tag object WORKS
                    tag = new Tag();
                    tag.blocks = new ArrayList();
                    char []txt = new char[tagEnd-tagStart+1];
                    System.arraycopy(input, tagStart, txt, 0, tagEnd-tagStart+1);
                    
                    // Split the tag by spaces
                    int cnt = 0, j = 0, ls = -1;
                    for(;j<txt.length;j++) {
                        if(txt[j] == ' ') {
                            if(j>0 && txt[j-1]==' ') {
                                ls = j;
                                continue; // ignore extra whitesp.
                            }
                            if(ls > -1)
                                tag.blocks.add(String.valueOf(txt, ls+1, j-ls-1));
                            else if(j>0) 
                                tag.blocks.add(String.valueOf(txt, 1, j-1));
                            ls = j;
                        } else {
                            if(j==txt.length-1) {
                                if(ls > -1)
                                    tag.blocks.add(String.valueOf(txt, ls+1, j-ls-1));
                                else
                                    tag.blocks.add(String.valueOf(txt, 1, j-1));
                            }
                        }
                    }
                    
                    if(tag.blocks.size()>0) {
                        String s;
                        // See if this tag contains an ID
                        for(j=0;j<tag.blocks.size();j++) {
                            s = (String) tag.blocks.get(j);
                            if(s.startsWith("id="))
                                tag.id = Integer.parseInt(s.substring(3));
                        }
                    }
                    
                    tag.data = String.valueOf(txt);
                    list.add(tag);
                    
                    tagStart = -1;
                }
                
                continue;
                    
            }
            
            // Check if there's text after the last tag
            if(i==length-1 && tagEnd > -1) {
                char []txt = new char[length-tagEnd-1];
                System.arraycopy(input, tagEnd+1, txt, 0, length-tagEnd-1);
                list.add(String.valueOf(txt));
            }
        }
        
        return list;
    }


Per e-mail generatie doe ik nu het volgende:
creeer stringbuffer
instanceof String --> append
instanceof Tag --> if/elseif om tag te herkennen, daarna een aantal append()'s om de betreffende code toe te voegen aan de e-mail.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
En voor de liefhebbers: ik vervang nu alle tags in een 20KB tekst, samengesteld uit meerdere content-blokken, in minder dan 10ms.

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Zou de performance verbeteren als je hiervoor 'gewoon' XML zou gebruiken en een goede XML parser met een SAX interface?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
B-Man:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
char []txt = new char[length-tagEnd-1]; 
System.arraycopy(input, tagEnd+1, txt, 0, length-tagEnd-1); 
list.add(String.valueOf(txt)); 

//kun je beter vervangen door 

list.add(new String(input, tagEnd+1, length-tagEnd-1));  
//is sneller aangezien er geen 
//twee keer een new moet worden gedaan. een value of doet een copy :)
//EN het leest ook beter :)

//ik denk dat er nog een hele hoop zo kan worden aangepakt :)


ik denk dat de overhead van SAX het zeker niet gaat versnellen (method calls ;) maar of het aan te raden om wat gebruiks vriendelijker te worden?. :) Voor een PHP deed ik heet eerst ook met een SAX geval maar aangezien het probleem kleiner is: zoeken naar een 1 special token zonder 4 methods voor elke tag... Template engines zijn nog steeds de snelste methode (behalve dan hardcoded JSP's :)). Wel effe wat anders dan de XSP waar ik nu mee bezig ben :) Dan weet je meteen hoe snel het is :)

edit:
als je toch je eigen tags maakt kun je eventueel dit wat optimisen je kunt je tags namelijk al parsed in je document zetten zodat ie helemaal geen 'look for whitespace moet doen etc etc.' maak gewoon een binary-encoded (serialize heb ik nog nooit gebruikt ;)text en zet die na een identifier (begin-tag) dan lees je die text in '1 fell swoop' naar een Tag Object. Dit is echt alleen als je veel tags hebt -

maar zo geef ik RDB data - over XML door. valt niet te ontleden en is enorm snel (zelfs na een base64 encode / decode - maar die kan ik vast wel wegkrijgen :).

[ Voor 60% gewijzigd door hobbit_be op 05-03-2003 16:59 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: ja, was een eerste testversie. Om eens te kijken of een eerste opzet qua snelheid in de buurt komt.

Ik zag net echter al dat het redelijk traag wordt zodra er een ArrayList met 50 stukken content verwerkt moet worden.

Wat bedoel je met "al parsed in je document zetten"? Kun je hier een simpel voorbeeld van geven?

Ik denk overigens dat het snelste zal zijn: eenmaal door de gehele string (na een vertaalslag naar een char[]), om vervolgens alle tags te vervangen. Nu doe ik namelijk een replace voor iedere tag apart.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
al parsed in je document zetten is om een structuur er in te zeggen die geen echte parsing vereist: daar waar de strcutuur al van gekent is:

een voorbeeld zijn image-formaten. Daar moet ook niet onderzocht of er nu wel een spatie staat of niet. stel je begint je tag met een && dan zet je daar in bytecode al achter wat deze tag heeft: &&[0dcf][ergss3745d74dd144fdfs87sdff] (de haakje is voor de duidelijkheid dus niet in je code]. dus na een && ga je de volgende 4 chars interpreteren als 1 integer deze zegt hoeveel tekst er volgt. Enzovoort. Dan hou je zelf bij hoe je het encode:
code:
1
2
3
4
5
6
7
8
1 x int : hoeveel blocks [NUB]
   NUB x 
      int : lengte van text in Block [LVB]
      LVB x char: gewone character data
1 x int :hoeveel attributes [NOA]
   NOA x
      String: naam van ID  [een string is een int [SizeOfString] gevolgd door SOS x char...
      String: data van attribute


snap je het een beetje? die ArrayList gaat vertragen als je hem niet genoeg initiieele ruimte geeft. Als je weet hoeveel tags erin een document zijn doe je:

ArrayList tTags = new ArrayList(aMaxTags_int); //als je het niet weet geef dan een Ruim getal. Ik geloof dat ie 16 pakt normaal en dan per 16 groeit.

Ik snap ook niet hoe je formaat eruit ziet van document (altijd het probleem als je optimised code ziet) anders zou ik meer specifieke tips kunnen geven...

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: in het kort:

ik heb een set strings (komen uit een db) die tezamen een "mail" omvatten. Op basis van gebruikersinvoer voeg ik de strings (content blokken) samen tot een "mail". Dit doe ik m.b.v. boolean expressies & BeanShell.
De strings voeg ik samen m.b.v. een StringBuffer.

Vervolgens voer ik een replace uit voor iedere tag die herkend moet worden (zie functie die ik eerder postte).

Voorbeeld:

Mail x

Blok 1: expressie (A==1 && B==2) (wordt dus alleen bij a=1 en b=2 in de mail opgenomen).
code:
1
Dit is de header bijvoorbeeld [tag1] [voornaam] [tag2] [andere_tag id=12 direct]


Blok 2: de rest, zonder conditie:
code:
1
Dit is de rest van de mail [afmelden.URL]


enz.

Is het zo duidelijk(er)?

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
yep :) maar ik zie direct dat je 'logica' hebt en dan wordt het wel erg ongemakkelijk om een direct parse te doen. Maar ik zie niet in jouw code dat die expressie wordt gedaan. Gebeurt dat na je de Tags hebt gecreert? If so dan kun je in ieder geval wel de techniek toepassen zoals ik al schreef. Je moet wel bedenken dat deze parsed template slechts 1 keer per type bericht moet worden gedaan (?) dus maakt het niet zo erg uit allemaal. Of doe je dit per elke keer want dan heb je niet begrepen what the point om een parsed template te gebruiken.

in die replace van Zynth zoekt hij slechts 1 x waar alle replaces kunnen gebeuren (ie jouw tags) en die vervangt hij dan later.

je parsed structuur is dus:

Parsed Template = Vector (of zoiets:)

0 [some static data]
1 [TAG name="name"]
2 [some static data] //er kunnen nooit 2 static achter elkaar
3 [TAG name="place"]
4 [TAG name="sex"]

HashMap

["name", 1] //de naam of key is voor later eenvoudig te werken
["place", 3] //het nummer is de index van de tag in je Vector
["sex", 4]

dit doe je dus een keer per soort document (met of zonder 'if's) je Vector is dus het maximale dcoument

dan per user die tags heeft ingevuld:

int tIndex = myHashMap.get(tCurrentTag.getName());
myVector.put(tIndex, tCurrentTag.getValue()); //insert into

do your logic door bijvoorbeeld de Tag objecten in je Vector als 'visible' te zetten ofzo..
code:
1
2
3
4
5
6
foreach(Element in mVector)
{
   if Element.isVisible() then
     myStringBuffer.append(Element.getValue())
   end if...
}


als je nested tags hebt (dus multiple times) dan zijn er andere mogelijkheden...

[ Voor 5% gewijzigd door hobbit_be op 05-03-2003 18:58 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Zo, heb nu een functie om bij het laden van de content blokken de zaak te splitsen die er als volgt uitziet:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public static ArrayList parseText(String text) {
        
        ArrayList list = new ArrayList();
        Tag tag;

        if(text.indexOf("[") == -1) {
            // Return a one-value ArrayList
            list.add(text);
            return list;
        }
        
        char []input = text.toCharArray();
        int i = 0, length = input.length, tStart = -1, tEnd = -1;
                
        tStart = text.indexOf("[");
        
        while(tStart != -1) {
            //log.debug("[ @ "+tStart);
            if(tEnd > -1) // Text between end of one and start of another
                list.add(new String(input, tEnd+1, tStart-tEnd-1));
            else if(tStart > 0) // Text before first tag
                list.add(new String(input, 0, tStart));
                
            tEnd = text.indexOf("]", tStart);
            //log.debug("] @ "+tEnd);
            
            if(tEnd == -1) break;
            
            char []txt = new char[tEnd-tStart+1];
            System.arraycopy(input, tStart, txt, 0, tEnd-tStart+1); 
            
            //tag = parseTag(txt);
            tag = parseTag(new String(input, tStart, tEnd-tStart+1));
            
            if(tag != null)
                list.add(tag);
                
            // Continue to next tag
            tStart = text.indexOf("[", tEnd);
            
            if(tStart == -1 && tEnd+1 < length) // Text after the last tag
                list.add(new String(input, tEnd+1, length-tEnd-1));
        }
        
        log.debug("Recognized "+list.size()+" blocks of content");
        
        return list;
    }


Deze verwerkt een tweetal mails van 20KB in 22ms.

[edit]

Ben net begonnen met testen m.b.t. het genereren van e-mails, en schrok ervan ;-) Zat net voor het eerst onder de 20ms... jaja, een 20KB mail in 11ms. Dat begint er meer op te lijken.

[ Voor 10% gewijzigd door B-Man op 05-03-2003 22:21 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: Ik neem aan dat je met je verwijzing naar de functie van Zynth op het grote "string replace topic" doelt?

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
zonder die logger.debug zal het al een pak minder ms zijn :)

tis mooi en al een heel pak meer leesbaar niet?

mischien kun je beter ipv parseTag(new String()) de parse tag vervangen
door de originele ofsets dus parseTag(input, offset) dan moet je gewoon
die offset optellen in je parseTag (maar is mierenneuken ;)

wat staat dit ernog te doen?

Java:
1
2
     char []txt = new char[tEnd-tStart+1]; 
      System.arraycopy(input, tStart, txt, 0, tEnd-tStart+1);     


txt wordt nergens gebruikt?

er is nog wel plaats voor optimalisatie: je zoekt nog steeds naar een eind tag? het helpt
als je ineens de tag kan verwerken en de offset effe meeverplaats (die int = size tip van me)

ik weet niet wat je doet in parseTag dus kan ik daar niets over zeggen...

maar nu heb ik toch een vraagje:

je schreef:

Deze verwerkt een tweetal mails van 20KB in 22ms

ok maar doe je nu telkens die parseText voor elke user?

dus als ik het goed begreep:

code:
1
2
3
4
5
6
7
aTypeOfBericht -> ParseToTags -> ParsedBericht
                                                    |
       aUserFills in Data (Tags)          + -----> Result 1
      aaNothee in Data (Tags)          + -----> Result 2
      aaNothee in Data (Tags)          + -----> Result 3

                //deze vult in tags die in aTypeOfBericht kunnen voorkomen



als je echter:

code:
1
2
aUserFills in Data (Tags) -> aTypeOfBericht -> ParseToTags -> ParsedBericht ->(+tags) Result
aUserFills in Data (Tags) -> aTypeOfBericht -> ParseToTags -> ParsedBericht ->(+tags) Result


dan heeft die parse geen enkele zin. dan kun je beter een hashmap van je user filled Tags maken en die parseTag van jouw dan enkel gebruiken voor het in te vullen maar dan moet
je het dus niet naar een ArrayList gaan schrijven maar gewoon restreeks naar je results.
(een soort van String.replace([["this", "withthis"],["andthis","withthis"],["andthis",""]]);

? :)

edit:
yep die topic...

[ Voor 10% gewijzigd door hobbit_be op 05-03-2003 22:43 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Zonder je gehele post te lezen: ik voor parseText en parseTag alleen uit als ik een mail voor het eerst uit de database vis. Na 30 seconden inactiviteit gebeurt dit overigens weer opnieuw (mijn cache systeem, zoals eerder gemeld).

Voor iedere te genereren e-mail loop ik door de ArrayLists, en append() ik aan een StringBuffer.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
...er is nog wel plaats voor optimalisatie: je zoekt nog steeds naar een eind tag? het helpt
als je ineens de tag kan verwerken en de offset effe meeverplaats (die int = size tip van me)...
Wat bedoel je?

De twee regels onnodige code had ik een paar seconden na het posten van de functie hier, al verwijderd uit mijn app. Toch bedankt voor het meedenken!

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hieronder een stukje log, om een indruk te geven.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
06 Mrz 2003 00:33:39,631 [W1  ] INFO  - Processing job 4 / 5
06 Mrz 2003 00:33:39,631 [W1  ] DEBUG - Getting batch from DataStore
06 Mrz 2003 00:33:39,631 [W1  ] DEBUG - Getting additional job data
06 Mrz 2003 00:33:39,690 [W1  ] DEBUG - Generate e-mail
06 Mrz 2003 00:33:39,691 [W1  ] DEBUG - texts appended
06 Mrz 2003 00:33:39,691 [W1  ] DEBUG - fields replaced
06 Mrz 2003 00:33:39,691 [W1  ] DEBUG - Maildispatcher initialized
06 Mrz 2003 00:33:39,692 [W1  ] DEBUG - Dispatching e-mail
06 Mrz 2003 00:33:39,692 [W1  ] DEBUG - Dispatch start
06 Mrz 2003 00:33:39,693 [W1  ] DEBUG - Message generated
06 Mrz 2003 00:33:39,694 [W1  ] DEBUG - Dispatched e-mail
06 Mrz 2003 00:33:39,705 [W1  ] DEBUG - Logged 819 bytes of traffic (job 1244)
06 Mrz 2003 00:33:39,715 [W1  ] INFO  - Job done, time: 84 ms
06 Mrz 2003 00:33:39,716 [W1  ] INFO  - Processing job 5 / 5
06 Mrz 2003 00:33:39,716 [W1  ] DEBUG - Getting batch from DataStore
06 Mrz 2003 00:33:39,716 [W1  ] DEBUG - Getting additional job data
06 Mrz 2003 00:33:39,724 [W1  ] DEBUG - Generate e-mail
06 Mrz 2003 00:33:39,725 [W1  ] DEBUG - texts appended
06 Mrz 2003 00:33:39,725 [W1  ] DEBUG - fields replaced
06 Mrz 2003 00:33:39,725 [W1  ] DEBUG - Maildispatcher initialized
06 Mrz 2003 00:33:39,725 [W1  ] DEBUG - Dispatching e-mail
06 Mrz 2003 00:33:39,725 [W1  ] DEBUG - Dispatch start
06 Mrz 2003 00:33:39,726 [W1  ] DEBUG - Message generated
06 Mrz 2003 00:33:39,727 [W1  ] DEBUG - Dispatched e-mail
06 Mrz 2003 00:33:39,730 [W1  ] DEBUG - Logged 819 bytes of traffic (job 1245)
06 Mrz 2003 00:33:39,747 [W1  ] INFO  - Job done, time: 31 ms

Te zien is dat er er nog wat ruimte voor optimalisatie is:
- Na "getting additional job data" trek ik nog wat data uit de database, dit kan nog geoptimaliseerd worden
- Na "dispatched e-mail" zitten nog wat teveel functieaanroepen, ook hier is nog wat te optimaliseren.

Maar het belangrijkste is dat ik nu in 1-2 ms de e-mail body kan genereren ;-)

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Zo, vandaag de app aan het profilen geweest met Sun's JVM, hieronder de top-10 en enkele details:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 rank   self  accum    bytes objs   bytes objs trace name
    1  4.31%  4.31%    98400    6   98400    6  1791 [B
    2  4.31%  8.63%    98400    6   98400    6  1889 [B
    3  4.31% 12.94%    98400    6   98400    6  1895 [B
    4  3.30% 16.24%    75320 1379  213656 5312  1965 [C
    5  2.97% 19.21%    67816  540   69856  576     1 [C
    6  2.88% 22.09%    65600    4 4395200  268  2966 [I
    7  2.87% 24.96%    65552    1   65552    1  1924 [B
    8  2.45% 27.41%    55896    1 2305952   88  3661 [C
    9  2.24% 29.65%    51056   12   51520   15    77 [B
   10  2.20% 31.85%    50200  235   50200  235     1 [B

TRACE 1791:
    com.mysql.jdbc.Buffer.<init>(Buffer.java:47)
    com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:186)
    com.mysql.jdbc.Connection.createNewIO(Connection.java:1582)
    com.mysql.jdbc.Connection.<init>(Connection.java:485)

TRACE 1895:
    java.io.BufferedOutputStream.<init>(BufferedOutputStream.java:63)
    com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:204)
    com.mysql.jdbc.Connection.createNewIO(Connection.java:1582)
    com.mysql.jdbc.Connection.<init>(Connection.java:485)

TRACE 1964:
    com.mysql.jdbc.ResultSet.getString(ResultSet.java:1764)
    com.mysql.jdbc.Connection.initializePropsFromServer(Connection.java:2245)
    com.mysql.jdbc.Connection.createNewIO(Connection.java:1603)
    com.mysql.jdbc.Connection.<init>(Connection.java:485)


De grootste bottleneck zit nu dus duidelijk in de MySQL JDBC driver.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Om de bottleneck te elimineren, ben ik vandaag begonnen met het schrijven van een MySQL driver. Aangezien ik mijn app ten alle tijde op MySQL zal draaien, heb ik niet per se JDBC nodig. Daarnaast trekt mijn app alleen integers en strings uit de database.

Heb vandaag een werkende versie in elkaar gezet, basic IO, querying, enz. Erg leuk om eens in het protocol van MySQL te duiken.

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Op zich waarschijnlijk interessant werk, maar niet zo verstandig naar mijn mening: de JDBC driver zal doorgroeien omdat hij onderhouden zal worden: jij kan je driver niet blijven onderhouden omdat het waarschijnlijk niet je 'core-business' zal worden. Je komt dus gegarandeerd op een moment dat je driver niet meer werkt op nieuwere MySQL versies en de JDBC driver je in performance voorbij streeft.

Kan je niet beter kijken waar de problemen in de MySQL driver zitten, die fixen en de verbeteringen insturen?

Een andere optie is natuurlijk om een beschaafd DBMS te gaan gebruiken. Naast de voordelen in het DBMS zelf is het ook zeer waarschijnlijk dat er een kwalitatievere JDBC driver is. Qua open oplossingen wordt de PostgreSQL driver zeer aktief onderhouden en is erg goed bij wat betreft de nieuwste Java goodies.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
In het algemeen werken "de bestaande oplossing passen me niet helemaal, dus dan doe ik het zelf wel" oplossingen dus niet echt (echt niet). Wat zelf voor de lol prutsen met zaken die eigenlijk al geimplementeerd zijn (zoals bijvoorbeeld een XML parser, een HTTP server of een template engine) is heel aardig, maar uiteindelijk kan je nooit op tegen mensen die van dergelijke zaken hun kern bezigheid hebben gemaakt. Alleen als jij het project zelf ook tot je kern bezigheid maakt, kan je wat zinvols bereiken.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
lange reactie ;)

De Connector/J JDBC driver cached veel te veel. Ik kan vervolgens kiezen: Connector/J aanpassen of zelf een veel simpelere nieuwe driver schrijven.

Mijn keuze gaat uit naar een simpele driver, aangezien deze gemakkelijker te onderhouden is. Daarnaast is het protocol, en mijn driver, erg klein. Mijn driver omvat een viertal classes van enkele honderden regels code.

Wat ook meespeelt is het feit dat Connector/J (bijna) alle JDBC specs implementeert, waarvan ik 99% niet nodig heb. Zaken zoals encodings enz.

Maar goed, ik heb de basis van de driver can cauco gebruikt als leerobject, en deze is van zichzelf al 40-50% sneller dan connector/J. Van de nieuwste versie is echter geen source beschikbaar, en daarnaast werkt de driver alleen i.c.m. Resin.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be schreef op 05 March 2003 @ 04:38:
nou - effe een late niter - tis nu 4:22am :)

maar ik me nu effe een replace die enorm veel sneller is... hoe enorm ben ik zelf
verrast van. :) euh de verschillen op grote text waarvan er een hoop echte replacen hangt is het verschil wel erg groot.

(per 72x zijn er 3 replaces)

72000 characters / test:100 (zijn dus 100x1000x3 replaces = 3.000.000)
ooString :2.578s 2 seconden
mBravenBoer :136.297s 2 minuten

toegegeven een replace op een document met 72000 zul je niet
vaak tegenkomen... door de enorme memory copies valt
stringbuffer uit de boot.

maar ook op kleinere is er een groot verschil. In neem aan
dat enkel bij een single replace er weinig verschil zal zijn.
edit: effe getest met een sample van 1.000.000 maar ook hier
is het verschil ongeveer x2.5... (niet dat je daar iets van zou merken)


720 characters / test:10000
0.985s - per keer is dat dus 0.09ms
3.453s x3 - per keer 0.35ms

7200 characters / test:1000
0.969s - per keer is dat dus 1ms
8.078s x8 - 8ms

ooh en dit is wanneer de de nieuwe tekst > oude tekst...

voor dezelfde monster replace maar dan nieuwe tekst < oude tekst:

ooString :1.296s //relatief dus ook een pak sneller...
mBravenBoer :110.391s

en ja ik test de correctheid v/d results ;)...

code release ik morgen wel omdat ie nog niet snel genoeg is :)
Hobbit_be: je hebt je code geloof ik nog niet gepost, ik wacht nog steeds met spanning ;-) op je supersnelle replace functie, dan kan ik vergelijken of het blok-append-algoritme of een replace sneller is. Wil je je functie ajb posten, dan kan ik er eens naar kijken.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
B-Man idd - werk had even (nu nog) voorrang. Hier is de link naar de file die ik gebruik
om te testen. Het includes mBravenBoer/Zynt/Onno implementaties alsook de code for al het timen enzo. alleen de package name zul je moeten veranderen (?). Normaal gebruik ik log4j maar heb er uit gehaald for ease of use. Het gebruikt nu alleen standaard java. Laat me weten wat ie zegt: je zult vast de tests kunnen verhogen voor een snellere PC... (ik had geen goesting om een 5 minuten te wachten per test)

http://www.onnos.com/dkitTest.java

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be: ga er nu even naar kijken. Heb zojuist zelf ook nog een replace functie gemaakt die twee keer zo snel is als mijn eerste functie (zie eerste pagina van dit topic).

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static String replace2(String orig, String from, String to) {
        
        int fromLength = from.length();

        if (fromLength == 0)
            throw new IllegalArgumentException("String to be replaced must not be empty");

        int start = orig.indexOf(from);
        if (start == -1) return orig;
        if (from.equals(to)) return orig;
        
        // Start replace
        
        int diff = to.length() - from.length();
        int tMax = orig.length()-from.length()+1;

        StrBuffer buffer;
        char[] origC = orig.toCharArray();
        char[] fromC = from.toCharArray();
        buffer = new StrBuffer(origC);
        int hits = 0, cp; // cp = Corrected Position
                
        first:for(int i=0;i<tMax;i++) {
            if(origC[i]!=fromC[0]) continue;
            
            for(int j=0;j<fromLength;j++)
                if(origC[i+j]!=fromC[j]) continue first;
                
            // hit!
            cp = i+(hits*diff); // Corrected position
            buffer.replace(cp, cp+fromLength, to);
            hits++;
        }

        return buffer.toString();
    }


In een String van 600 chars 11 maal een code vervangen door een string die langer is, 1000x achter elkaar, duurt met mijn eerste functie zo'n 120ms, en met deze functie zo'n 60ms.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
euh is nog 1 line teveel in mijn source

// String.valueOf(tSource); line: 369 - ik denk wel dat java hem wegcompileerd

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Wat denk je van mijn functie?

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
kun je wel even StrBuffer meegeven? anders kan ik het niet testen

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
public class StrBuffer {
    /** 
     * This variable 'numchar' is the number of characters in the buffer.
     */
    int numchar;

    /**
     * The variable 'mybuf' is used for character storage.
     */
    char mybuf[];

    /**
     * Make an empty string buffer with 80 characters of storage.
     */
    public StrBuffer() {
        this(80);
    }

    /**
     * Make an empty string buffer with 'len' characters of storage.
     *
     * @param      len   the initial storage capacity.
     * @exception  NegativeArraySizeException  if the 'len' less than 0.
     */
    public StrBuffer(int len) {
        this.mybuf = new char[len];
    }
    
    public StrBuffer(char[] data) {
        this.mybuf = data;
        this.numchar = data.length;
    }

    /**
     * Calling this method has same effect as setLength(0)
     * Clears the contents of the string buffer.
     */
    public void resetLength() {
        this.numchar = 0;
    }
    
    public int getLength() {
        return numchar;
    }

    public void setCapacity(int len) {
        if (len <= mybuf.length)
            return;
        mybuf = new char[len];
        numchar = 0;
    }
    
    public char[] getBuffer() {
        if(numchar==0) return new char[0];
        
        char []ret = new char[numchar];
        System.arraycopy(mybuf, 0, ret, 0, numchar);
        return ret;
    }
    
    public void setBuffer(char []buffer) {
        mybuf = buffer;
        numchar = buffer.length;
    }
    
    void ensureStorage(int size) {
        if(size > numchar)
            moreStorage(size);
    }

    /**
     * Expand the storage size to at least 'minStorage' number of characters.
     */
    void moreStorage(int minStorage) {
        int newStorage = (this.mybuf.length * 2) + 5;
        if (newStorage < minStorage)
            newStorage = minStorage;
        char newBuf[] = new char[newStorage];
        System.arraycopy(this.mybuf, 0, newBuf, 0, this.numchar);
        this.mybuf = newBuf;
    }

    /**
     * Appends the argument string to this string buffer. 
     *
     * @param   str   a string.
     * @return  this string buffer
     */
    public StrBuffer append(String str) {
        int oldlen = str.length();
        int newlen = this.numchar + oldlen;
        if (newlen > this.mybuf.length)
            moreStorage(newlen);
        str.getChars(0, oldlen, this.mybuf, this.numchar);
        this.numchar = newlen;
        return this;
    }

    public StrBuffer append(int i) {
        return append(String.valueOf(i));
    }

    public StrBuffer append(char[] ch) {
        int len = ch.length;
        int newcount = numchar + len;
        if (newcount > mybuf.length)
            moreStorage(newcount);

        System.arraycopy(ch, 0, mybuf, numchar, len);
        numchar = newcount;
        return this;
    }

    //public StrBuffer append(Object o) {
    //  return append(o.toString());
    //}

    public StrBuffer append(char[] text, int start, int len) {
        int newcount = numchar + len;
        if (newcount > mybuf.length)
            moreStorage(newcount);
        System.arraycopy(text, start, mybuf, numchar, len);
        numchar = newcount;
        return this;
    }

    public StrBuffer replace(int start, int end, String str) {
        if (start < 0) throw new StringIndexOutOfBoundsException(start);
        if (end > numchar) end = numchar;
        if (start > end) throw new StringIndexOutOfBoundsException();

        int len = str.length();
        int newCount = numchar + len - (end - start);
        if (newCount > mybuf.length)
            moreStorage(newCount);
            
        // Copy everything after our str to a new position
        if((end-start) != len) // Only when the length is different
            System.arraycopy(mybuf, end, mybuf, start + len, numchar - end);
        str.getChars(0, len, mybuf, start);
        numchar = newCount;
        return this;
    }

    /**
     * Returns a new string based on contents of string buffer.
     *
     * @return  a string
     */
    public String toString() {
        return new String(this.mybuf, 0, this.numchar);
    }
}

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Mijn testcode:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void main(String[] args) {
        // Now test the new tag splitter
        Stopwatch s = new Stopwatch();
        s.start();
        String myText = "Dit is een [test] met een [test2] en nog [test] 2etcetera\n" +
            "dsiafuhdfnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n" +
            "fddsfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n" +
            "fjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n" +
            "[test][test][test2]reahfhhhhhhhhhhhhhhhhhhhhhhhh [test] hhhhhhhhhhh\n" +
            "fasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajjjjjjj [test] jjjjjjjjjjjjjjjjj\n" +
            "[test]nvnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n" +
            "[test]nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn[test]nnnnnnnnnnnnnnnnnn\n" +
            "[test2]hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n";
        String myText2 = "abc[test] __ [test] 123 [test] xyz\ntweede [test] text [test] etceter";
        int cnt = 10000;
        for(int i=0;i<cnt;i++) {
            Utility.replaceOld(myText, "[test]", "haha");
            Utility.replaceOld(myText, "[test2]", "haha2");
        }
        System.out.println(s.elapsed());
        s.start();
        StrBuffer test = new StrBuffer(myText.toCharArray());
        for(int i=0;i<cnt;i++) {
            Utility.replace(test, "[test]", "haha");
            Utility.replace(test, "[test2]", "haha2");
            test.setBuffer(myText.toCharArray());
        }
        System.out.println(s.elapsed());
    }


Resultaat:

1401
656

Dat is dus 0,0656ms per keer

[edit]
Mijn Stopwatch class is simpelweg een wrapper om m.b.v. System.currentTimeMillis() te rekenen.

[ Voor 12% gewijzigd door B-Man op 09-03-2003 17:07 ]


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
thx heb em effie getest

dkit.admin.dkitTest
validating replace:

ooString Result:
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
mBravenBoer Result:
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
Zynt Result:
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
B-Man Result:
OOPS.in thOOPSple, a loop nestedunderneath in anotherOOPSxample

> !!!! INCORRECT REPLACE !!!

//-------------------------------------------------------------------
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 4
testing with 72 characters and repeating test:1

testing with 720 characters and repeating test:10000
ooString :1.125 /ms
mBravenBoer :3.484 /ms
mZynt :1.422 /ms
B-Man :1.672 /ms

testing with 7200 characters and repeating test:1000
ooString :1.094 /ms
mBravenBoer :8.172 /ms
mZynt :1.359 /ms
B-Man :6.937 /ms

//-------------------------------------------------------------------
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 12

testing with 720 characters and repeating test:10000
ooString :1.156 /ms
mBravenBoer :3.735 /ms
mZynt :1.656 /ms
B-Man :1.937 /ms

testing with 7200 characters and repeating test:1000
ooString :1.203 /ms
mBravenBoer :8.688 /ms
mZynt :1.765 /ms
B-Man :6.953 /ms

//-----------------------------------------------------------------------
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 7

testing with 720 characters and repeating test:10000
ooString :1.094 /ms
mBravenBoer :3.218 /ms
mZynt :1.453 /ms
B-Man :0.922 /ms

testing with 7200 characters and repeating test:1000
ooString :1.047 /ms
mBravenBoer :3.141 /ms
mZynt :1.39 /ms
B-Man :0.922 /ms

The verdict:

a) je replace werkt niet :) (heb je oude code gegeven?)
b) hij is trager in alle gevallen behalve de laatste (trager dan zynt/onno)
c) het laatste geval geeft geen verschil in tijd door wat be dunkt
dat hij iets geks doet: maar wil best checken. Aangezien mijn code
is optimised for same-size replaces vindt ik het dus heel gek.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hmm, ging hier ook net wat mis. Ik denk dat het in mijn StrBuffer class zit. Ik denk dat ik die hele class niet gebruik (komt van het net, geen eigen code), en de code die ik nodig heb direct in mijn eigen functie zet. Back in 15 mins.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hobbit: ik heb zojuist je ooString klasse opgenomen in mijn eigen test (hierin zit nu ook mijn aangepaste replace, werkt nu volgens mij wel goed), en dit zijn de resultaten:

664 // die van mij
1023 // ooString.replaceUltraSnel met een string als input
1402 // ooString.replace

Testcode:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public static void main(String[] args) {
        // Now test the new tag splitter
        Stopwatch s = new Stopwatch();
        s.start();
        String myText = "Dit is een [test] met een [test2] en nog [test] 2etcetera\n" +
            "dsiafuhdfnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n" +
            "fddsfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n" +
            "fjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n" +
            "[test][test][test2]reahfhhhhhhhhhhhhhhhhhhhhhhhh [test] hhhhhhhhhhh\n" +
            "fasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajjjjjjj [test] jjjjjjjjjjjjjjjjj\n" +
            "[test]nvnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\n" +
            "[test]nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn[test]nnnnnnnnnnnnnnnnnn\n" +
            "[test2]hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n";
        String myText2 = "abc[test] __ [test] 123 [test] xyz\ntweede [test] text [test] etceter";
        int cnt = 10000;
        for(int i=0;i<cnt;i++) {
            Utility.replaceOld(myText, "[test]", "haha");
            Utility.replaceOld(myText, "[test2]", "haha2");
        }
        System.out.println(s.elapsed());
        s.start();
        //StrBuffer test = new StrBuffer(myText.toCharArray());
        char [] ha = new char[0];
        for(int i=0;i<cnt;i++) {
            ha = myText.toCharArray();
            Utility.replace(ha, "[test]", "haha");
            Utility.replace(ha, "[test2]", "haha2");
        }
        System.out.println(s.elapsed());
        s.start();
        for(int i=0;i<cnt;i++) {
            ooString.replaceUltrasnel(myText, "[test]", "haha");
            ooString.replaceUltrasnel(myText, "[test2]", "haha2");
        }
        System.out.println(s.elapsed());
        s.start();
        for(int i=0;i<cnt;i++) {
            ooString.replace(myText, "[test]", "haha");
            ooString.replace(myText, "[test2]", "haha2");
        }
        System.out.println(s.elapsed());
        ha = myText.toCharArray();
        ha = Utility.replace(ha, "[test]", "haha");
        ha = Utility.replace(ha, "[test2]", "haha2");
        System.out.println(new String(ha));
    }

Zoals je kunt zien, is mijn code een stuk sneller. Graag je reactie ;-)
Voor de volledigheid hier mijn huidige replace code:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public static char[] replace(char []orig, String from, String to) {
        
        int fromLength = from.length();

        if (fromLength == 0)
            throw new IllegalArgumentException("String to be replaced must not be empty");

        if (from.equals(to)) return orig;
        
        // Start replace
        
        int diff = to.length() - from.length();
        //int tMax = buffer.getLength()-from.length()+1;
        int tMax = orig.length-from.length()+1;
        int toLength = to.length();

        char[] fromC = from.toCharArray();
        char[] toC = to.toCharArray();
        int hits = 0, cp; // cp = Corrected Position
        int cl = orig.length;   // current length
        
        //System.out.println("before hits");
        int h = 0;
        
        if(diff > 0) {
            first:for(int i=0;i<tMax;i++) {
                if(orig[i]!=fromC[0]) continue;
                
                for(int j=0;j<fromLength;j++)
                    if(orig[i+j]!=fromC[j]) continue first;
                    
                // hit!
                //cp = i+(hits*diff); // Corrected position
                
                h++;
            }
            
            if(h==0) {
                System.out.println("no hits");
                return orig;
            }       
            
            //System.out.println("after hits: "+h);
            
            // Create new array if necessary
            if(h>0 && diff>0) {
                char []tmp = new char[cl+(h*diff)];
                cl = tmp.length;
                System.out.println(orig.length+", "+tmp.length);
                System.arraycopy(orig, 0, tmp, 0, orig.length);
                orig = tmp;
            }
        }
                
        first:for(int i=0;i<tMax;i++) {
            if(orig[i]!=fromC[0]) continue;
            
            for(int j=0;j<fromLength;j++)
                if(orig[i+j]!=fromC[j]) continue first;
                
            // hit!
            
            if(diff != 0) {
                int size = orig.length-i-fromLength;
                System.arraycopy(orig, i+fromLength, orig, i+toLength, size);
                if(diff < 0) cl += diff;
            }
            // Now replace
            to.getChars(0, toLength, orig, i);
            hits++;
            
            i += toLength-1;
        }
        
        if(diff<0) {
            // Copy to a smaller array
            char []c = new char[cl];
            System.arraycopy(orig, 0, c, 0, cl);
            orig = c;
        }
        
        return orig;
    }

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Nog wat testinfo: als ik mijn myText var 10x achter elkaar plak, en dezelfde serie tests er 10.000x op loslaat:

code:
1
2
3
4
5
6
7
8
9
10
11
// myText
Old: 1401
New: 708
ooString mb: 1023
ooString fast: 1393

// myText x 10
Old: 14352
New: 9908
ooString mb: 12770
ooString fast: 14551

Waarin old mijn oude replace is, new mijn nieuwe, ooString mb mbravenboer, en ooString fast de replace() in ooString.

Wederom is mijn replace de snelste, ik kom er niet uit... vermoeidheid denk ik.

[update]
vervangende string korter:
code:
1
2
3
4
5
6
7
8
9
Old: 1933
New: 720
ooString mb: 1035
ooString fast: 1388

Old: 14074
New: 11812
ooString mb: 14358
ooString fast: 13898

[ Voor 17% gewijzigd door B-Man op 09-03-2003 19:48 ]


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
effe checken - maar als je char[] gaat doorgeven kan het ook een pak sneller he dat is een hele hoop gecopy weg, dus geen appelen met peren vergelijken :) maar ga effe checken want die toChars die jij gebruikt ken ik niet en die ziet er interessant uit :) wel leuk zo'n sessie..

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
hmm toch niet zo net:

java.lang.ArrayIndexOutOfBoundsException72, 99

als de nieuwe string > oude string dus er zit nog ergens een fout in bij je...

edit:
en ook nog een foute bij mezelf ontdekt gelukkig niet ernstig:

maar mijn berekening van tMax index moet niet

final int tMaxIndex = tSourceLength - tNewStringLength + 1;

maar:

final int tMaxIndex = tSourceLength - tOldStringLength + 1;

doh!!!

[ Voor 53% gewijzigd door hobbit_be op 09-03-2003 20:22 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Er zit nog steeds een bug in mijn replace... als de vervangende string langer is dan het origineel, dan krijg ik een error. Zometeen even naar kijken.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Oke, ik ben met de bug bezig... Maarre, wat denk je van mijn snelheidstest? Zoals je kunt zien is mijn functie sneller? Althans, voorzover ik het nu al heb kunnen testen (newstring even lang als oldstring en newstring < oldstring)...

[ Voor 33% gewijzigd door B-Man op 09-03-2003 20:33 ]


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
euh ik ondek net nog wel een grove logica fout bij jouw - die ik eerst ook maakte trouwens:

jij modified in sommige gevallen de orig[] parameter: dwz dat SOMS de char[] die jij doorgeeft ook modified wordt teruggegeven EN de origenele veranderd:

in dat geval is het een ander soort replace die inderdaad een pak sneller is.

voorbeeld:

Java:
1
2
3
4
5
6
7
8
9
10
11
String tOrig = "this is an example";
char[] tFast = tOrig.toArray();

char[] tResult = BManReplace(tFast, "this", "test") 
//zoals eerder vermeld als jouw als ik "test met groter" zou pakken crashed jouw replace

//dan is tResult = "test is an example";

//MAAR:

//tFast = "test is an example";  //???? 


did kan natuurlijk het gebruik zijn als je wil want het het is idd sneller (2x full mem copy)

maar dan moet je de functie wel zo vermelden. als ik mijn functie ook zo maak gaat het bij mij ook een pak sneller. jouw replace is dus meer een :

someStringClass.replace("fast", "hello"); //zonder een return...

stel dat je met je template 3 keer die gebruikt dan vind die in alle volgende gevallen de tag
niet meer - :)

laat iets weten mocht je de New > Old probleem heb opgelost dan kunnen we nog eens comparen...

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Om toch fatsoenlijk te kunnen vergelijken init ik mijn char array opnieuw per iteratie:
Java:
1
2
3
4
5
6
char [] ha = new char[0];
        for(int i=0;i<cnt;i++) {
            ha = myText.toCharArray();
            Utility.replace(ha, in1, out1);
            Utility.replace(ha, in2, out2);
        }


Ik heb de bug ook gevonden, zometeen even eruit halen.

Overigens is dit gedrag me bekend. Het is sneller, en daarom acceptabel.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
heb effe dezelfde logica gestoken in een 'snelle' versie van m'n replace (ook met char[] en
may modify original)

//New < Old
testing with 720 characters and repeating test:10000
ooString :1.204 /ms
B-Man 2: 1.609 /ms
Onno Faster 2: 0.828 /ms

testing with 7200 characters and repeating test:1000
ooString :1.078 /ms
B-Man 2: 6.782 /ms
Onno Faster 2: 0.782 /ms

//New == Old
testing with 720 characters and repeating test:10000
ooString :0.969 /ms
B-Man 2: 0.656 /ms
Onno Faster 2: 0.688 /ms

testing with 7200 characters and repeating test:1000
ooString :0.984 /ms
B-Man 2: 0.657 /ms
Onno Faster 2: 0.687 /ms

in mijn test gevallen is mijn search sneller bij NEW < OLD maar de jouwe is dan weer sneller als ze gelijk zijn... :) het zou dus kunnen dat jouw search voor een 'match' sneller is dan die van mij want jouw copy is trager :) - maw ze zijn wellicht te combineren.. ook jouw fast return als eerste character niet klopt is interessant...

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
bug is eruit, moest corrigeren op basis van de originele input als de vervangende string langer is:

Java:
1
2
3
4
5
6
7
8
// hit!
            
            if(diff != 0) {
                if(diff<0) size = orig.length-i-fromLength;
                else        size = ol-i-fromLength;
                System.arraycopy(orig, i+fromLength, orig, i+toLength, size);
                if(diff < 0) cl += diff;
            }


output met een vervangende string die langer is:
code:
1
2
3
4
5
6
7
8
9
Old: 1949
New: 853
ooString mb: 1320
ooString fast: 1431

Old: 14962
New: 11619
ooString mb: 19320
ooString fast: 14877

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit: alweer winst, we stoten het vorige string-replace topic van de troon ;)

Post je ajb je code?

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
ik denk het vast wel: zowel synth code als mbravenboer heb ik al uit de benchmark gehaalt die zijn minstens 2x (mbravenboer x8) trager...

ik had nog in mijn nieuwe fast een foutje (ik gaf bij een kleiner result de grotere door) dus nu is mijn 'fast' replaces iets trager.

gek genoeg is is nog altijd sneller bij kleinere gevallen en de jouwe nog steeds troon voor als ze gelijk zijn :)

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Zoals ik al aangaf wil ik graag een blik werpen op je meest recente functie, dan kan ik kijken wat er te combineren valt.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
euh wat is "ol" bij jouw? en waar heb je 'size' nu gedefinieerd?

ik zie nog een snellere loop voor jouw :) in deel 2 van je search begin je opnieuw
van 0 maar je kunt al ineens naar 1 skippen :)

[ Voor 58% gewijzigd door hobbit_be op 09-03-2003 21:28 ]


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
here is mijn versie alla different rules :)
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    public static char[] replace(char[] aSource, String aOld, String aNew)
    {
       final int tSourceLength = aSource.length;
        if (tSourceLength == 0)
        {
            return aSource;
        }
        final int tOldStringLength = aOld.length();
        if (tOldStringLength == 0)
        {
            return aSource;
        }
        if (aOld.equals(aNew)) // :) you NEVER know penatly should be light
        {
            return aSource;
        }
         final int tNewStringLength = aNew.length(); 
         final char[] tOld = aOld.toCharArray();
         final char[] tNew = aNew.toCharArray();

        final int tMaxIndex = tSourceLength - tOldStringLength + 1;
        int tIndex = 0;
        int tSearchIndex; //to prevent reinit of int var in case java doesn't see it..

        if (tNewStringLength == tOldStringLength)
        {
             nextChar:while (tIndex < tMaxIndex) //ugly ? yes but nice :)
            {
                tSearchIndex = 0; //restart search
                while (tSearchIndex < tNewStringLength)
                {
                    if (aSource[tIndex++] != tOld[tSearchIndex++]) //is ++Int faster???
                    {
                        continue nextChar; //restart search
                    }
                }
                System.arraycopy(tNew, 0, aSource,
                                 tIndex - tNewStringLength,
                                 tNewStringLength);
            }
            return aSource;
        }
        
        int tWriteToIndex = 0;
        int tReadFromIndex = 0;
        int tOriginalCopySize;
        int tReplaceCount = 0; 
        
        if (tNewStringLength < tOldStringLength)
        {
             nextChar3:while (tIndex < tMaxIndex)
            {
                tSearchIndex = 0; //restart search
                while (tSearchIndex < tOldStringLength)
                {
                    if (aSource[tIndex++] != tOld[tSearchIndex++])
                    {
                        continue nextChar3; //restart search
                    }
                } 
                tOriginalCopySize = tIndex - tReadFromIndex - tOldStringLength;
                if (tOriginalCopySize > 0) 
                { 
                    System.arraycopy(aSource, tReadFromIndex, aSource,
                                     tWriteToIndex, tOriginalCopySize);
                    tWriteToIndex += tOriginalCopySize; //offset write position
                }
                System.arraycopy(tNew, 0, aSource, tWriteToIndex,
                                 tNewStringLength);
                tWriteToIndex += tNewStringLength;
                tReadFromIndex = tIndex;
                tReplaceCount++; 
            }
            if (tReplaceCount == 0)
            {
                return aSource; 
            }
            tOriginalCopySize = tSourceLength - tReadFromIndex;
            if (tOriginalCopySize > 0)
            {
                System.arraycopy(aSource, tReadFromIndex, aSource,
                                 tWriteToIndex, tOriginalCopySize);
                tWriteToIndex += tOriginalCopySize; //this is length
            }
            int tSize = tSourceLength +
                        ( (tNewStringLength - tOldStringLength) * tReplaceCount);

            char[] tBuffer = new char[tSize]; 
            System.arraycopy(aSource, 0, tBuffer, 0, tSize);

            return tBuffer; 

        }

        int tMaxReplaceCount = mReplaceIndex.length; //cache this
        nextChar2:while (tIndex < tMaxIndex)
        {
            tSearchIndex = 0; //restart search
            while (tSearchIndex < tOldStringLength)
            {
                if (aSource[tIndex++] != tOld[tSearchIndex++])
                {
                    continue nextChar2; //restart search
                }
            }
            mReplaceIndex[tReplaceCount++] = tIndex - tOldStringLength;
            if (tReplaceCount >= tMaxReplaceCount) //painful but unlikely
            {
                int[] tReplaceIndex = new int[tMaxReplaceCount +
                                      mReplaceIndexGrowth];
                System.arraycopy(mReplaceIndex, 0, tReplaceIndex, 0,
                                 tMaxReplaceCount);
                tMaxReplaceCount = mReplaceIndex.length;
            }
        }
        if (tReplaceCount == 0)
        {
            return aSource; //no matches...
        }
        int tSize = tSourceLength +
                    ( (tNewStringLength - tOldStringLength) * tReplaceCount);

        char[] tBuffer = new char[tSize]; //ugly but required unless
        for (int tReplaceIndex = 0; tReplaceIndex < tReplaceCount;
                                 tReplaceIndex++)
        {
            tIndex = mReplaceIndex[tReplaceIndex];
            tOriginalCopySize = tIndex - tReadFromIndex;
            if (tOriginalCopySize > 0) //copy original text piece
            {
                System.arraycopy(aSource, tReadFromIndex, tBuffer,
                                 tWriteToIndex, tOriginalCopySize);
                tWriteToIndex += tOriginalCopySize; //offset write position
            }
            System.arraycopy(tNew, 0, tBuffer, tWriteToIndex,
                             tNewStringLength);
            tWriteToIndex += tNewStringLength;
            tReadFromIndex = tIndex + tOldStringLength; //offset read 'jump' over the replace..
        }
        if (tReadFromIndex < tSourceLength)
        {
            System.arraycopy(aSource, tReadFromIndex, tBuffer,
                             tWriteToIndex, tSourceLength - tReadFromIndex);
        }
        return tBuffer; //the only usefull String Copy...
    }

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
hobbit_be schreef op 09 March 2003 @ 21:26:
euh wat is "ol" bij jouw? en waar heb je 'size' nu gedefinieerd?

ik zie nog een snellere loop voor jouw :) in deel 2 van je search begin je opnieuw
van 0 maar je kunt al ineens naar 1 skippen :)
ol = old length, een int die de oorspronkelijke lengte van mijn input char[] bevat. size is een int die alleen betekenis in de tweede lus heeft.

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Oh, en pffffff, wat een lap code zeg, daar stelt die van mij niet veel bij voor ;)

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
yow!

ik heb effe jouw 'match' in mijn code gepropt en idd hij is sneller ik heb hem NOG wat geoptimaliseerd en het is idd die eerste check die het em doet :)

dwz: dat je bijvoorbeeld voor elke lengte van old string een nieuwe search kunt doen voor extra speed... :) zonder die toChars (maar pure System) is die dus nog sneller... als new==old dan is de nieuwe al 2x zo snel als de oude (maar die moet natuurlijk copying enzo)...

ik ga effe < > ook doen:

de search is nu:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final char tFirst = tOld[0]; //:) simpel maar genoeg voor 100ms :)
first:for (tIndex = 0; tIndex < tMaxIndex; tIndex++)
{
    if (aSource[tIndex] != tFirst)
    {
        continue;
    }

    for (tSearchIndex = 1; tSearchIndex < tOldStringLength; tSearchIndex++)
    {
        if (aSource[tIndex + tSearchIndex] != tOld[tSearchIndex])
        {
            continue first;
        }
    }

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
dit is mijn laatste post vandaag :)

a) ik krijg met ol = orig.length nog steeds ArrayIndexOutOfBound. ik snap
ook niet veel v/j code daaromtrent...

b) laatste post is al achterhaalt - doen ik die 'trick' om eerste (indexOf) te doen
op mijn while loop loslaat ging ie nog sneller (dus alvast bedankt!!!)

c) mijn originele (dus propere ooString) is nu ook weer een stuk sneller:

d) final rsesult:

Old > New

testing with 720 characters and repeating test:10000
BMan - Onno: 0.781 /ms
ooString : 0.984 /ms
B-Man 2: 1.547 /ms

testing with 7200 characters and repeating test:1000
BMan - Onno: 0.782 /ms
ooString : 0.938 /ms
B-Man 2: 6.812 /ms

Old = New

testing with 720 characters and repeating test:10000
BMan - Onno: 0.563 /ms
B-Man 2: 0.625 /ms
ooString : 0.844 /ms

testing with 7200 characters and repeating test:1000
BMan - Onno: 0.562 /ms
B-Man 2: 0.641 /ms
ooString : 0.89 /ms

Kan het sneller ? - yep door x-aantal speciale gevallen los te laten
maar deze is universeel en misschien kan deze nog sneller afhankelijk
van JVM implementatie: qua algorithme zitten we goed :)

edit:
NEW > OLD werkt ook waanzinnig snel nu...

[ Voor 3% gewijzigd door hobbit_be op 09-03-2003 22:56 ]


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Goed nieuws hobbit! Ben nu mijn MySQL driver aan het afronden, die is ook erg snel vergeleken met de MM.MySQL driver.

Om duidelijk te maken wat ol en size zijn hierbij de gehele (werkende! ook indien newLen > oldLen) functie:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public static char[] replace(char []orig, String from, String to) {
        
        int fromLength = from.length();

        if (fromLength == 0)
            throw new IllegalArgumentException("String to be replaced must not be empty");

        if (from.equals(to)) return orig;
        
        // Start replace
        
        int diff = to.length() - from.length();
        //int tMax = buffer.getLength()-from.length()+1;
        int tMax = orig.length-from.length()+1;
        int toLength = to.length();

        char[] fromC = from.toCharArray();
        char[] toC = to.toCharArray();
        int hits = 0, cp; // cp = Corrected Position
        int cl = orig.length;   // current length
        int ol = cl,size;           // original length
        
        //System.out.println("before hits");
        int h = 0;
        
        if(diff > 0) {
            first:for(int i=0;i<tMax;i++) {
                if(orig[i]!=fromC[0]) continue;
                
                for(int j=0;j<fromLength;j++)
                    if(orig[i+j]!=fromC[j]) continue first;
                    
                // hit!
                //cp = i+(hits*diff); // Corrected position
                
                h++;
            }
            
            if(h==0) {
                System.out.println("no hits");
                return orig;
            }       
            
            //System.out.println("after hits: "+h);
            
            // Create new array if necessary
            if(h>0 && diff>0) {
                char []tmp = new char[cl+(h*diff)];
                cl = tmp.length;
                //System.out.println("add "+(h*diff));
                //System.out.println(orig.length+", "+tmp.length);
                System.arraycopy(orig, 0, tmp, 0, orig.length);
                orig = tmp;
            }
        }
                
        first:for(int i=0;i<tMax;i++) {
            if(orig[i]!=fromC[0]) continue;
            
            for(int j=0;j<fromLength;j++)
                if(orig[i+j]!=fromC[j]) continue first;
                
            // hit!
            
            if(diff != 0) {
                if(diff<0) size = orig.length-i-fromLength;
                else        size = ol-i-fromLength;
                System.arraycopy(orig, i+fromLength, orig, i+toLength, size);
                if(diff < 0) cl += diff;
            }
            // Now replace
            to.getChars(0, toLength, orig, i);
            hits++;
            
            i += toLength-1;
        }
        
        if(diff<0) {
            // Copy to a smaller array
            char []c = new char[cl];
            System.arraycopy(orig, 0, c, 0, cl);
            orig = c;
        }
        
        return orig;
    }

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13-05 20:11
Mag ik die replace ook in C implementeren met de JNI? Dan zullen we nog wel eens zien wat snel is. :P

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Soultaker: ik las laast dat sommige zaken m.b.v. JNI juist trager zijn dan m.b.v. JIT in de JVM... Zal eens kijken of ik de nieuwsgroep-post terug kan vinden. Het ging in ieder geval zo'n 33% trager m.b.v. JNI.

Maarre, feel free om het te proberen. Als het sneller gaat, dan heb ik er wel oren naar ;) Werk overigens wel op linux...

[ Voor 24% gewijzigd door B-Man op 10-03-2003 00:14 ]


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13-05 20:11
B-Man schreef op 10 March 2003 @ 00:13:
Soultaker: ik las laast dat sommige zaken m.b.v. JNI juist trager zijn dan m.b.v. JIT in de JVM... Zal eens kijken of ik de nieuwsgroep-post terug kan vinden. Het ging in ieder geval zo'n 33% trager m.b.v. JNI.

Maarre, feel free om het te proberen. Als het sneller gaat, dan heb ik er wel oren naar ;) Werk overigens wel op linux...
Ik ben de afgelopen nachten niet voor drie uur naar bed geweest omdat ik projectdocumentatie af moet maken, dus ik heb daar echt geen tijd voor (wel GoT checken tussendoor natuurlijk :P ). Maar ik ben benieuwd waar die tijd in gaat zitten. Als je met behulp van reflectie allerlei methoden bij objecten moet gaan zoeken, is de JNI waarschijnlijk erg traag, maar als je gewoon drie strings binnenkrijgt (die je als character arrays kunt benaderen) en een enkele string moet construeren, zoals in dit geval, dan kan ik me moeilijk voorstellen dat er nog verdere overhead optreedt (misschien zijn native method calls iets kostbaarders maar dan nog).

Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Soultaker: overigens is System.arraycopy() al een native functie.

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
B-Man: (sorry dat ik dit moet laten zien)

Original: example.in this example, a loop nestedunderneath in another loop.example

[example gets replaced]

validating replace:

ooString:
very big replace.in this very big replace, a loop nestedunderneath in another loop.very big replace

mBravenBoer:
very big replace.in this very big replace, a loop nestedunderneath in another loop.very big replace

B-Man Final Result:
very big replace.in this very big replace, a loop nestedunderneath in another loo ... (some weird characters)

B-Man - Onno
very big replace.in this very big replace, a loop nestedunderneath in another loop.very big replace

maar hij geeft geen geheugen fouten meer... dus alleen een copy op het laatste gaat er fout...

times:

Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 4

testing with 720 characters and repeating test:10000
ooString : 0.985 /ms
B-Man Final: 1.625 /ms
BMan - Onno: 0.765 /ms

testing with 7200 characters and repeating test:1000
ooString : 0.921 /ms
B-Man Final: 6.813 /ms
BMan - Onno: 0.75 /ms

Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 7


testing with 720 characters and repeating test:10000
ooString : 0.875 /ms
B-Man Final: 0.641 /ms
BMan - Onno:0.562 /ms

testing with 7200 characters and repeating test:1000
ooString : 0.922 /ms
B-Man Final: 0.656 /ms
BMan - Onno: 0.563 /ms

Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 12

testing with 720 characters and repeating test:10000
ooString : 1.032 /ms
B-Man Final: 1.734 /ms
BMan - Onno: 0.797 /ms

testing with 7200 characters and repeating test:1000
ooString :1.047 /ms
B-Man Final: 6.39 /ms
BMan - Onno: 0.828 /ms

ik heb effe je code ontleed en als je echt speed nodig hebt (dus als diff <> 0) dan is je code echt niet optimaal: heel veel memory copy dat niet nodig is. Als ik grotere tests draai moet ik zolang wachten dat ik de app afbreek (heapsize maar ook veel te veel reshuffle)

ik zal morgen de final geven , want een deel van de code is van jouw en jij hebt hem vast meer nodig dan ik... (vandaag HAD ik aan een invocation engine moeten werken - java is daarin toch niet zo mooi als ik dacht)

BTW als je naar de results kijkt is iedere result per deel eigenlijk gelijk aan het aantal replaces. (720x10000 = 7200x1000).

Mocht je die MM.MySQL driver klaarkrijgen ben ik daar ook zeer in geinteresseerd BTW. ook ik heb alleen standaard spul nodig... :)

Soultaker: tja als je me effe alleen laten met masm zal ik het vast ook nog een pak sneller kunnen krijgen. Ik zou zeggen dat de code gemiddeled 10x 100x sneller zou zijn met een native (misschien meer met SSE)

Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 29-06-2020
toch maar effe posten:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  //make these private if syncronised is required
  //otherwise these get reused
    static private int[] mReplaceIndex = new int[10000];
    static private int mReplaceIndexGrowth = 10000;

 //the replace. returns a result, but may change aSource object as well
      public static char[] BManOnnoReplace(char[] aSource, String aOld,
                                         String aNew)
    {
        final int tSourceLength = aSource.length;
        if (tSourceLength == 0)
        {
            return aSource;
        }
        final int tOldStringLength = aOld.length();
        if (tOldStringLength == 0)
        {
            return aSource;
        }
//probably remove this since why would anyone replace the same?
//        if (aOld.equals(aNew)) // :) you NEVER know penatly should be light
//        {
//            return aSource;
//        }

        final int tNewStringLength = aNew.length();
        final char[] tOld = aOld.toCharArray();
        final char[] tNew = aNew.toCharArray();

        final int tMaxIndex = tSourceLength - tOldStringLength + 1;
        int tIndex = 0;
        int tSearchIndex; 
        final char tFirst = tOld[0]; 
//we cache first of old - quite a speed difference
        if (tNewStringLength == tOldStringLength)
        {
            nextChar:while (tIndex < tMaxIndex) 
            {
                if (aSource[tIndex++] != tFirst)
                {
                    continue;
                }
             //if we are here then 1st character is already same so skip
                tSearchIndex = 1; 
                while (tSearchIndex < tNewStringLength)
                {

                    if (aSource[tIndex++] != tOld[tSearchIndex++]) //is ++Int faster???
                    {
                        continue nextChar; //restart search
                    }
                }
                System.arraycopy(tNew, 0, aSource,
                                 tIndex - tNewStringLength,
                                 tNewStringLength);
            }
            return aSource; //BAIL! -> modifies aSource
        }

        int tWriteToIndex = 0;
        int tReadFromIndex = 0;
        int tOriginalCopySize;
        int tReplaceCount = 0;

        if (tNewStringLength < tOldStringLength)
        {
            nextChar3:while (tIndex < tMaxIndex)
            {
                if (aSource[tIndex++] != tFirst)
                {
                    continue;
                }

                tSearchIndex = 1; //restart search
                while (tSearchIndex < tOldStringLength)
                {
                    if (aSource[tIndex++] != tOld[tSearchIndex++])
                    {
                        continue nextChar3; //restart search
                    }
                }
                tOriginalCopySize = tIndex - tReadFromIndex -
                                    tOldStringLength;
 //copy piece missed from last - minimum copy - no duplicate copying
 //what so ever!!!
                if (tOriginalCopySize > 0)
                {
                    System.arraycopy(aSource, tReadFromIndex, aSource,
                                     tWriteToIndex, tOriginalCopySize);
                    tWriteToIndex += tOriginalCopySize; //offset write position
                }
                System.arraycopy(tNew, 0, aSource, tWriteToIndex,
                                 tNewStringLength);
                tWriteToIndex += tNewStringLength;
                tReadFromIndex = tIndex;
                tReplaceCount++;
            }
            if (tReplaceCount == 0)
            {
                return aSource;
            }
//we still need to copy last bit
            tOriginalCopySize = tSourceLength - tReadFromIndex;
            if (tOriginalCopySize > 0)
            {
                System.arraycopy(aSource, tReadFromIndex, aSource,
                                 tWriteToIndex, tOriginalCopySize);
                tWriteToIndex += tOriginalCopySize; //this is length
            }
//we need to return correct array not aSource coz lengths are different
            int tSize = tSourceLength +
                        ( (tNewStringLength - tOldStringLength) *
                         tReplaceCount);
//when doing a STring return -> no penalty!
            char[] tBuffer = new char[tSize];
            System.arraycopy(aSource, 0, tBuffer, 0, tSize);

            return tBuffer;

        }

//case NEW > OLD
        int tMaxReplaceCount = mReplaceIndex.length; //cache this
        nextChar2:while (tIndex < tMaxIndex)
        {
            if (aSource[tIndex++] != tFirst)
            {
                continue;
            }

            tSearchIndex = 1; //restart search
            while (tSearchIndex < tOldStringLength)
            {
                if (aSource[tIndex++] != tOld[tSearchIndex++])
                {
                    continue nextChar2; //restart search
                }
            }
            mReplaceIndex[tReplaceCount++] = tIndex - tOldStringLength;
            if (tReplaceCount >= tMaxReplaceCount) //painful but unlikely
            {
                int[] tReplaceIndex = new int[tMaxReplaceCount +
                                      mReplaceIndexGrowth];
                System.arraycopy(mReplaceIndex, 0, tReplaceIndex, 0,
                                 tMaxReplaceCount);
                mReplaceIndex = tReplaceIndex;
                tMaxReplaceCount = mReplaceIndex.length;
            }
        }
        if (tReplaceCount == 0)
        {
            return aSource; //no matches...
        }
        int tSize = tSourceLength +
                    ( (tNewStringLength - tOldStringLength) * tReplaceCount);

        char[] tBuffer = new char[tSize]; //ugly but required unless
//do the actual replacing - again no duplicate copies... 
        for (int tReplaceIndex = 0; tReplaceIndex < tReplaceCount;
                                 tReplaceIndex++)
        {
            tIndex = mReplaceIndex[tReplaceIndex];
            tOriginalCopySize = tIndex - tReadFromIndex;
            if (tOriginalCopySize > 0) //copy original text piece
            {
                System.arraycopy(aSource, tReadFromIndex, tBuffer,
                                 tWriteToIndex, tOriginalCopySize);
                tWriteToIndex += tOriginalCopySize; //offset write position
            }
            System.arraycopy(tNew, 0, tBuffer, tWriteToIndex,
                             tNewStringLength);
            tWriteToIndex += tNewStringLength;
            tReadFromIndex = tIndex + tOldStringLength; //offset read 'jump' over the replace..
        }
        if (tReadFromIndex < tSourceLength)
        {
            System.arraycopy(aSource, tReadFromIndex, tBuffer,
                             tWriteToIndex, tSourceLength - tReadFromIndex);
        }
        return tBuffer; //the only usefull String Copy...
    }


iemand nog ideetjes?

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 13-05 17:10
Hmm.. ik denk ik probeer ik eens wat. Ff een algoritme geschreven en getest mbv die dkitTest.java :)

result:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 4
testing with 72 characters and repeating test:1
ooString :0.0 /ms
mBravenBoer :0.0 /ms
mZynt :0.0 /ms
MarcJ : 0.01 /ms
testing with 720 characters and repeating test:10000
ooString :0.571 /ms
mBravenBoer :0.791 /ms
mZynt :0.581 /ms
MarcJ : 0.631 /ms
testing with 7200 characters and repeating test:1000
ooString :0.521 /ms
mBravenBoer :1.782 /ms
mZynt :0.501 /ms
MarcJ : 0.461 /ms
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 12
testing with 72 characters and repeating test:1
ooString :0.0 /ms
mZynt :0.0 /ms
MarcJ : 0.0 /ms
testing with 720 characters and repeating test:10000
ooString :0.561 /ms
mBravenBoer :0.891 /ms
mZynt :0.731 /ms
MarcJ : 0.651 /ms
testing with 7200 characters and repeating test:1000
ooString :0.551 /ms
mBravenBoer :1.892 /ms
mZynt :0.731 /ms
MarcJ : 0.481 /ms


Efficiënter bij hele grote reeksen dus, maar minder bij de wat kortere. Ik denk dat ik nu ff wat ga fine-tunen :)

edit2:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
validating replace:
ooString Result: 
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
mBravenBoer Result: 
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
Zynt Result: 
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
MarcJ Result: 
OOPS.in this OOPS, a loop nestedunderneath in another loop.OOPS
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 4
testing with 72 characters and repeating test:1
ooString :0.0 /ms
mZynt :0.0 /ms
MarcJ : 0.0 /ms
testing with 720 characters and repeating test:10000
ooString :0.581 /ms
mZynt :0.6 /ms
MarcJ : 0.491 /ms
testing with 7200 characters and repeating test:1000
ooString :0.541 /ms
mZynt :0.521 /ms
MarcJ : 0.5 /ms
testing with 72000 characters and repeating test:100
ooString :1.192 /ms
mZynt :0.701 /ms
MarcJ : 0.611 /ms
testing with 720000 characters and repeating test:10
ooString :1.242 /ms
mZynt :1.632 /ms
MarcJ : 0.711 /ms
Performing A Set Of Tests Depending On Search Size:
Size Of Old: 7
Size Of New: 12
testing with 72 characters and repeating test:1
ooString :0.0 /ms
mZynt :0.0 /ms
MarcJ : 0.0 /ms
testing with 720 characters and repeating test:10000
ooString :0.551 /ms
mZynt :0.681 /ms
MarcJ : 0.521 /ms
testing with 7200 characters and repeating test:1000
ooString :0.541 /ms
mZynt :0.64 /ms
MarcJ : 0.471 /ms
testing with 72000 characters and repeating test:100
ooString :0.871 /ms
mZynt :1.262 /ms
MarcJ : 0.551 /ms
testing with 720000 characters and repeating test:10
ooString :1.242 /ms
mZynt :1.322 /ms
MarcJ : 0.881 /ms

8)
sorry mBravenBoer, maar jouw code wat echt te traag voor 72000 characters...

[ Voor 51% gewijzigd door Marcj op 10-03-2003 11:32 ]

Pagina: 1 2 Laatste