[Java] Syntax Highlighting, JVM discussie

Pagina: 1
Acties:
  • 105 views sinds 30-01-2008
  • Reageer

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik ben op dit moment bezig met een extensie van een DefaultStyledDocument om te kunnen syntax highlighten. Het werk op zich wel oke, maar het is langzaam (ik vind het te langzaam 3000 regels duurt 10 seconden op p733 256mb met jdk1.4beta2 en jdk1.3.1)

Ik override op dit moment de insertString en mijn classe is geextend van DefaultStyledDocument. Als ik een string binnenkrijg met de insertString methode dan ga ik eerst kijken hoeveel tekst totaal gescanned moet worden en dat lex ik, en dan stukje voor stukje super.insertString aanroepen met de goeie kleuren. Het werkt allemaal goed.

Nu komt de grote maar. Ik ben door de insertString van DefaultStyledDocument gaan ploegen en daar wordt elke keer gelocked en geunlocked. Dus uiteindelijk ben je superveel tijd kwijt om te synchronizeren. En je bent dus onnodig langzaam. Een oplossing is dus aan het begin van mijn insert een lock aan te vragen en aan het einde weer te unlocken. Maar dan moet ik een hele lading methodes overriden (om daar de lock uit te halen) maar dit werkt ook niet.

Mijn vraag is of iemand ervaringen heeft met syntax highlighten. Ik heb al veel stukken code bekeken maar de meeste dingen waren slecht geimplementeerd, of slecht gedocumenteerd en wijken bijna allemaal af van DefaultStyledDocument.

[edit] vriendlijkheid++ && spelfouten-=2

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik ben er weleens mee bezig geweest, maar eerlijk gezegd was dat ook een hele slechte implementatie :) .

Misschien dat het leerzaam kan zijn om eens naar het component te kijken wat gebruikt wordt in jext. Ik gebruik nu alleen nog maar jext voor java ontwikkeling en ik moet zeggen dat de performance zeer goed is.

Misschien dat het zelfs wel verstandiger is om gewoon ook dat component te gebruiken. Het is zeer krachtig en configureerbaar :) . Volgens mij is het oorspronkelijk afkomstig van jedit, maar dat weet ik niet zeker.

Het is tenslotte niet voor niets open-source he? ;)

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


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zet het binnenkort wel even op deze pagina. De lexer is gemaakt in ANTLR maar er kan ook zo een andere op. Maar programmeren met die Element structuur is wel lastig!! (hoef ik gelukkig niet te doen omdat ik gebruik maak van DefaultStyledDocument).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Voor iedereen die dit nog een keer doorleest. Als je gebruik maakt van DefaultStyledDocument dan is je geheugen verbruik veel te groot, voor een file van 100k zit ik over de 40 mb geheugen. Dit komt door die akelige attribute set die aan ieder element zit en die in zich een Hashtable heeft(welliswaar 3 buckets).

Ik denk niet dat defaultStyledDocument voor grote documenten geschikt is. Tis trouwens ook veeeeeeel te traag.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Voor een syntax highlighter is het niet echt nodig om een complete lexer te gebruiken :) Zoals mbravenboer al zei, kijk eens in de source van Jext, daarbij is het namelijk best slim gedaan ;)
Ik weet niet wat de DefaultStyledDocument-klasse is, maar als je het alá Jext doet hoeft het helemaal niet veel geheugen te kosten.
(Ik heb zelf een editor met syntax highlighter geschreven in C++, en daarbij van Jext afgekeken :))

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op donderdag 13 september 2001 17:48 schreef marcusk het volgende:
Voor een syntax highlighter is het niet echt nodig om een complete lexer te gebruiken :) Zoals mbravenboer al zei, kijk eens in de source van Jext, daarbij is het namelijk best slim gedaan ;)
Ik weet niet wat de DefaultStyledDocument-klasse is, maar als je het alá Jext doet hoeft het helemaal niet veel geheugen te kosten.
(Ik heb zelf een editor met syntax highlighter geschreven in C++, en daarbij van Jext afgekeken :))
Ik gebruik de lexer die ik ook voor de parser gebruik, daarom hoef ik maar op 1 plek iets te wijzigen. En mbv JProbe ben ik er achter gekomen dat ik 5% aan de tijd van het lexen ben en 95% vd tijd de kleuren aan het doorvoeren ben. Het lexen is dus niet het probleem.

Ik heb net Jext ook even opgehaald en een dik bestand inladen dat merk je niet eens terwijl je bij mijn implementatie toch echt even zoet bent :) of liever :( Ze hebben het inderdaad erg snel geimplementeerd.

De DefaultStyledDocument is de model van een grafisch op te maken TextArea. Heb helaas voorlopig te weinig tijd om met die syntax highlighting bezig te gaan. Heb het er eerst in gezet als probeerseltje

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik heb onderdelen van Jipe http://jipe.sourceforge.net/ gebruikt om te syntax highlighten. Ten 1e. het component dat geschreven is, is bloedsnel (45.000 regels in 5 seconden op p733 met jdk1.4beta3), ten 2e zijn de componenten redelijk los geprogrammeerd (dus niet verweven) en ten 3e neemt het bijna geen geheugen in beslag. Als iemand er nog een keer mee bezig wil is dit zeker een aanrader...

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zie dat JEditTextArea van Jipe ook is gemaakt door Slava Pestov netzo als die van Jext en JEdit. Het edit component van JEdit en Jext zijn helemaal geintegreerd met het systeem en zijn zonder wijzigingen niet te gebruiken (bv niet
publieke constructors). Ook doordat ze volledig geintergreerd zijn met het systeem kun je er weinig mee.

De oplossing hiervoor is:
http://syntax.jedit.org/
Dit bevat alle componenten die nodig zijn om te highlighten en zijn niets anders dan een cleane versie van de componenten Jipe. Voor de mensen die willen highligten is dit denk ik de oplossing.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Bedankt dat je je bevindingen even doorgeeft :) . Ik moet nog steeds die XML verlichting gaan doen, dus ik ben je dankbaar ;) .

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


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik ben nu de code wat aan het bekijken en er zijn wat verschillen tussen jedit syntax package en tussen jipe. De tabsize valt niet meer in te stellen en autoindent funcionaliteit is niet meer aanwezig. Ik heb al een aantal 'upgrades' gedaan (autoindent weer aan, bug uit jdk1.4 eruit)
en ben nu bezig om het syntax highlighten een beetje na te lopen. Ik zie dat er nog wel een paar plaatsen zijn waar geoptimaliseer kan worden..

bv..
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static boolean regionMatches(boolean ignoreCase, Segment text,
                        int offset, String match)
    {
        int length = offset + match.length();
        char[] textArray = text.array;
        if(length > text.offset + text.count)
            return false;
        for(int i = offset, j = 0; i < length; i++, j++)
        {
            char c1 = textArray[i];
            char c2 = match.charAt(j);
            if(ignoreCase)
            {
                c1 = Character.toUpperCase(c1);
                c2 = Character.toUpperCase(c2);
            }
            if(c1 != c2)
                return false;
        }
        return true;
    }

na optimalisatie. (de if die kan uit de lus)
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
public static boolean regionMatches(boolean ignoreCase, Segment text,int offset, String match)
    {
        int length = offset + match.length();
        char[] textArray = text.array;
        if(length > text.offset + text.count)
            return false;

        if(ignoreCase)
        {
            for(int i = offset, j = 0; i < length; i++, j++)
            {
                if(Character.toUpperCase(textArray[i])!=Character.toUpperCase(match.charAt(j)))
                    return false;
            }
        }
        else
        {
            for(int i = offset, j = 0; i < length; i++, j++)
            {
                if(textArray[i]!=match.charAt(j))
                    return false;
            }
        }

        return true;
    }

En ik ben nu bezig met een snellere char compare.

dit is de huidige to uppercase code van Character
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
 public static char toUpperCase(char ch) {
      char mapChar = ch;
      int val = A[Y[((X[ch>>5]&0xFF)<<4)|((ch>>1)&0xF)]|(ch&0x1)];

      if ((val & 0x00010000) != 0) {
        if ((val & 0x07FC0000) == 0x07FC0000) {
            switch(ch) {
              // map chars with overflow offsets
              case '\u00B5' : mapChar = '\u039C'; break;
              case '\u017F' : mapChar = '\u0053'; break;
              case '\u1FBE' : mapChar = '\u0399'; break;
              // map char that have both a 1:1 and 1:M map
              case '\u1F80' : mapChar = '\u1F88'; break;
              case '\u1F81' : mapChar = '\u1F89'; break;
              case '\u1F82' : mapChar = '\u1F8A'; break;
              case '\u1F83' : mapChar = '\u1F8B'; break;
              case '\u1F84' : mapChar = '\u1F8C'; break;
              case '\u1F85' : mapChar = '\u1F8D'; break;
              case '\u1F86' : mapChar = '\u1F8E'; break;
              case '\u1F87' : mapChar = '\u1F8F'; break;
              case '\u1F90' : mapChar = '\u1F98'; break;
              case '\u1F91' : mapChar = '\u1F99'; break;
              case '\u1F92' : mapChar = '\u1F9A'; break;
              case '\u1F93' : mapChar = '\u1F9B'; break;
              case '\u1F94' : mapChar = '\u1F9C'; break;
              case '\u1F95' : mapChar = '\u1F9D'; break;
              case '\u1F96' : mapChar = '\u1F9E'; break;
              case '\u1F97' : mapChar = '\u1F9F'; break;
              case '\u1FA0' : mapChar = '\u1FA8'; break;
              case '\u1FA1' : mapChar = '\u1FA9'; break;
              case '\u1FA2' : mapChar = '\u1FAA'; break;
              case '\u1FA3' : mapChar = '\u1FAB'; break;
              case '\u1FA4' : mapChar = '\u1FAC'; break;
              case '\u1FA5' : mapChar = '\u1FAD'; break;
              case '\u1FA6' : mapChar = '\u1FAE'; break;
              case '\u1FA7' : mapChar = '\u1FAF'; break;
              case '\u1FB3' : mapChar = '\u1FBC'; break;
              case '\u1FC3' : mapChar = '\u1FCC'; break;
              case '\u1FF3' : mapChar = '\u1FFC'; break;
              // ch must have a 1:M case mapping, but we
              // can't handle it here. Return ch.
              // since mapChar is already set, no need
              // to redo it here.
              //default  : mapChar = ch;
            }
        }
        else {
            int offset = val  << 5 >> (5+18);
            mapChar =  (char)(ch - offset);
        }
      }
      return mapChar;
    }

Ik weet dat hierin voor het standaard character bereik (dus 0..255) nogal grote optimalisaties mogelijk zijn.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Een andere hele eenvoudige optimalisatie (waardoor je een uppercase conversie kan uitschakelen) is door alle keywords meteen uppercase te bewaren.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op woensdag 14 november 2001 19:56 schreef mbravenboer het volgende:
Bedankt dat je je bevindingen even doorgeeft :) . Ik moet nog steeds die XML verlichting gaan doen, dus ik ben je dankbaar ;) .
Bij die syntax jedit versie zit ook een xml kleurder, scheelt je weer werk. :)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
deze lijkt me wel snel.. weet iemand nog iets beters?
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
char toUpperCase(char c)
    {
        char result;
        switch(c)
        {
            case 'a' :  result = 'A';   break;
            case 'b' :  result = 'B';   break;
            case 'c' :  result = 'C';   break;
            case 'd' :  result = 'D';   break;
            case 'e' :  result = 'E';   break;
            case 'f' :  result = 'F';   break;
            case 'g' :  result = 'G';   break;      
            case 'h' :  result = 'H';   break;
            case 'i' :  result = 'I';   break;
            case 'j' :  result = 'J';   break;
            case 'k' :  result = 'K';   break;
            case 'l' :  result = 'L';   break;
            case 'm' :  result = 'M';   break;
            case 'n' :  result = 'N';   break;
            case 'o' :  result = 'O';   break;
            case 'p' :  result = 'P';   break;
            case 'q' :  result = 'Q';   break;
            case 'r' :  result = 'R';   break;
            case 's' :  result = 'S';   break;
            case 't' :  result = 'T';   break;
            case 'u' :  result = 'U';   break;
            case 'v' :  result = 'V';   break;
            case 'w' :  result = 'W';   break;
            case 'x' :  result = 'X';   break;
            case 'y' :  result = 'Y';   break;
            case 'z' :  result = 'Z';   break;
            default:    result = c;
                
        }
        
        return result;
    }

Verwijderd

kan je niet 26 bij een letter optellen om zo de uppercase te krijgen ?
Ik weet niet meer hoe dat precies gaat though :)

En moet je niet doen
Char result = c;
voor het geval dat c al uppercase is.


edit: oops :o

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op donderdag 15 november 2001 12:32 schreef Snow-in-a-can het volgende:
kan je niet 26 bij een letter optellen om zo de uppercase te krijgen ?
Ik weet niet meer hoe dat precies gaat though :)

En moet je niet doen
Char result = c;
voor het geval dat c al uppercase is.


edit: oops :o
Dat kan wel, maar moet je 2 ifstatements (of 1 met 2 voorwaarden in conditie) uitvoeren en een add.. het bovenstaande lijkt me toch een stuk sneller. En ik zie in mijn code geen fouten by the way.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hum, ik vraag me af of die switch echt wel sneller is...

Ik weet niet precies hoe die gecompileerd wordt, maar hij moet voor het default geval behoorlijk wat cases nalopen. Een simpele vergelijking op de waarde van de char (allemaal primitieven) zou weleens sneller kunnen zijn...

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


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op donderdag 15 november 2001 19:44 schreef mbravenboer het volgende:
Hum, ik vraag me af of die switch echt wel sneller is...

Ik weet niet precies hoe die gecompileerd wordt, maar hij moet voor het default geval behoorlijk wat cases nalopen. Een simpele vergelijking op de waarde van de char (allemaal primitieven) zou weleens sneller kunnen zijn...
Bij een switch case statement wordt een adres berekening gedaan geloof ik. Dus ongeacht het aantal cases blijft de switch case even snel. Ik ga het nog even nakijken (dit herinner ik me nog uit mijn c/pascal tijdperk).

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
http://www-2.cs.cmu.edu/~jch/java/speed.html
Know your switches:
A switch statement is compiled into one of two bytecodes, depending on the sparsity of the cases you're switching on. The first, where the numbers are close together, uses a fast direct lookup. The second, where the numbers are further apart, uses a slower search through a table. Look at the bytecode your code is compiled into to find which you're using (tip from Greg McClement). This is particularly important if you're trying to replace a sequence of if statements with a switch (tip from Erik Meade).
Zal nog ff verder kijken....

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


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op donderdag 15 november 2001 21:03 schreef mbravenboer het volgende:
http://www-2.cs.cmu.edu/~jch/java/speed.html
[..]

Zal nog ff verder kijken....
thanx.. ben zelf ook nog even aan het kijken..

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Als ik naar al die complexiteit van het switch statement kijk, dan kan ik inderdaad beter een if statement gebruiken..
code:
1
2
3
4
if(c>='a' and c<='z')
{
   c+=..;
}

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hum dat docje is eigenlijk best leuk :)
The Java Virtual Machine is stack-oriented, with most operations taking one or more operands from the operand stack of the Java Virtual Machine's current frame, or pushing results back onto the operand stack. A new frame is created each time a Java method is invoked, and with it is created a new operand stack and set of local variables for use by that method (see Section 3.6, "Frames" ). At any one point of the computation, there are thus likely to be many frames and equally many operand stacks per thread of control, corresponding to many nested method invocations. Only the operand stack in the current frame is active.
Hoe zou het dan met gebruik van registers zitten? Die zullen toch wel ergens voor gebruikt worden?

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


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Alarmnummer: Als ik naar al die complexiteit van het switch statement kijk, dan kan ik inderdaad beter een if statement gebruiken..
Dat vermoed ik ook, maar een simpele test zegt natuurlijk meer dan mijn vermoedens :) .

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


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Op donderdag 15 november 2001 21:12 schreef mbravenboer het volgende:

[..]

Dat vermoed ik ook, maar een simpele test zegt natuurlijk meer dan mijn vermoedens :) .
Misschien kunnen we met nog een paar andere tweakers die ook belangstelling hebben het syntax jedit (JEditTextArea) component wat nieuw leven inblazen. Ik zie dat op
http://sourceforge.net/projects/jedit-syntax/
er weinig animo voor is, terwijl het een ongelovelijk goed component is. Helaas jammer dat het JEditTextArea component uit JEdit helemaal geintegreerd is met hun systeem, zodat het praktisch onbruikbaar is geworden.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik ga het hier even mee proberen.
code:
1
2
3
4
5
6
7
8
9
    public final static int difference = 'Z'-'z';

    public static char toUpperCase(char c)
    {
        if(c>='a'&&c<='z')
            return (char)(c+difference);
        else
            return c;
    }

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Snelheid blijft hetzelfde, denk dat ik ergens anders nu moet gaan bezuinigen. Ligt het hier in ieder geval niet aan :P

Denk dat ik JProbe er maar eens op moet loslaten.

  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

Op donderdag 15 november 2001 21:10 schreef mbravenboer het volgende:
Hum dat docje is eigenlijk best leuk :)
Hoe zou het dan met gebruik van registers zitten? Die zullen toch wel ergens voor gebruikt worden?
als ik het goed herinner heeft een JVM geen registers... Natuurlijk worden wel de registers van het platform (IA32, Motorola, ...) gebruikt (door de JVM) maar de bytecode die je genereert voor je JVM werkt niet met registers...

Kortom: een JVM is stack-based 8-)

Voor *veel* info hierover, boek tip: Computerarchitectuur, 2e editie, Andy Tanenbaum

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: als ik het goed herinner heeft een JVM geen registers... Natuurlijk worden wel de registers van het platform (IA32, Motorola, ...) gebruikt (door de JVM) maar de bytecode die je genereert voor je JVM werkt niet met registers...
Maar het zou wel heel makkelijk zijn als er in de bytecode wel word aangegeven welke variabelen goed in een register opgeslagen zouden kunnen worden.

Omdat de JVM platform-onafhankelijk is en het gedrag en het aantal van de registers enorm verschilt per platform is het natuurlijk onmogelijk om vast te leggen wat er in registers opgeslagen kan worden...

Het kan echter behoorlijk wat tijd kosten om dat allemaal goed uit te gaan zoeken at run-time (zeker als er naar native code gecompileerd gaat worden). Hints in de bytecode zouden misschien een heleboel kunnen helpen? Iets langere comile tijd is natuurlijk niet zo boeiend...
Voor *veel* info hierover, boek tip: Computerarchitectuur, 2e editie, Andy Tanenbaum
Dat schijnt inderdaad een goed boek te zijn ja... Voorlopig houd ik het maar bij m'n oude dictaat en mijn huidige compiler implementatie docs :) .

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


  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

tuurlijk zou het handig zijn, maar denk je niet dat de verschillende JVM's zelf niet zo slim zijn om uit te zoeken wat het best in de registers van het onderliggende platform gestopt kan (of moet) worden?

Btw, dat boek is echt een aanrader maar als je al flink ingelezen (het Web doet wonderen ;)) bent in onderwerpen als de werking van de JVM, de stack, de bytecode, dan heb je niet zoveel meer aan dit boek op het gebied van Java... niettemin staat er nog heel veel andere interessante info over CPU's en OS'en in waarvan de oren van veel tweakers hier zullen klapperen van verbazing :) ... ofzoiets... wazige zin, limoen!! ;)

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: tuurlijk zou het handig zijn, maar denk je niet dat de verschillende JVM's zelf niet zo slim zijn om uit te zoeken wat het best in de registers van het onderliggende platform gestopt kan (of moet) worden?
Uiteraard kan een JVM dat prima (en zelfs beter dan at-compile time uiteraard), maar de kern van mijn stukje was nu juist dat het leuk zou zijn als je in Java bytecode al zou kunnen aangeven wat er in een register opgeslagen zou kunnen worden en wat absoluut niet (heb ook net geleerd dat die variable dan 'escaped' ;) ).

Op deze manier hoeft een JVM dus at run-time minder werk te doen, waardoor de benodigde opstart kleiner kan zijn... De JVM hoeft in feite alleen maar naar de architectuur te loeren en te beslissen in hoeverre er ook gebruik van registers gemaakt kan worden voor de 'mogelijkheden'. Als er niet genoeg registers zijn wordt er gewoon voor de stack gekozen, net als voor de variabelen die sowieso niet op in registers kunnen worden opgeslagen.

Het kan dus allemaal wel at-runtime, maar waarom niet zoveel mogelijk at-compiletime... :) .
Btw, dat boek is echt een aanrader maar als je al flink ingelezen (het Web doet wonderen ;)) bent in onderwerpen als de werking van de JVM, de stack, de bytecode, dan heb je niet zoveel meer aan dit boek op het gebied van Java... niettemin staat er nog heel veel andere interessante info over CPU's en OS'en in waarvan de oren van veel tweakers hier zullen klapperen van verbazing :) ...
Ik zal het onthouden :) . Ik ben de laatste tijd iets meer geinteresseerd in compilers en dergelijke, maar op het moment heb ik genoeg documentatie. Computer-architectuur hebben we al gehad in een vrij primitieve vorm. De werking van stacks, registers, frames, static links en dergelijke wordt allemaal behandeld bij de diverse compiler-bouw vakken. Misschien moet ik het eens inkijken om te zien of het nog iets toevoegd :) .

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


  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

ik deel je mening ten dele (mooie zin is dat ;)):

bij het bytecode maken wil je zelf (handmatig) aan gaan geven wat in registers moet? dat lijkt me niet handig want ik denk dat de JVM beter weet wat erin moet dan jijzelf...

bij het bytecode maken wil je de compiler alvast laten uitzoeken wat handig in registers kan? lijkt me wederom niet erg handig want het is echt *heel* platform afhankelijk wat er wel en niet in registers moet, en vooral *wanneer* ... dus als jouw bytecode ineens op Motorola moet draaien ipv. IA32, dan kan het best zo zijn dat het toch slimmer is om andere zaken in de registers te hebben op bepaalde momenten, of de volgorde van verwerking in de registers ff te veranderen...

Hier komt trouwens nog bij dat het niet zo is dat bepaalde variabelen op het onderliggende platform continu in registers staan, en andere continu op de stack. Dat zou je de uitwerking van je theorie aanzienlijk vergemakkelijken maar er is een fundamenteel verschil tussen IA32 die (voorzover ik weet) alleen maar kan rekenen in/met de registers, en een JVM die alleen maar rekent in/op de stack (!)

Samenvattend: het is niet handig om de bytecode al register-georienteerd te maken omdat de verschillende CPU's (en de bijbehorende registerverwerking) gewoon niet gelijk werken...
En believe me, als het mogelijk was had Sun het al lang gedaan, met als belangrijkste reden natuurlijk de snelheid van uitvoering op hun JVM...

Een simpel voorbeeld is volgens mij de vergelijking tussen IA32 en de Sun UltraSparc... die laatste heeft veel meer registers voor algemene bewerkingen (add, multiply, ...), terwijl IA32 eigenlijk maar 1 (jawel, één!) register heeft hiervoor (EAX).
Hierbij laat ik SSE/SSE2/MMX even buiten beschouwing omdat ik daar (nog) geen kaas van gegeten heb :)

edit:
heb m'n text nog iets genuanceerd

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op vrijdag 16 november 2001 23:06 schreef limoentje het volgende:
bij het bytecode maken wil je zelf (handmatig) aan gaan geven wat in registers moet? dat lijkt me niet handig want ik denk dat de JVM beter weet wat erin moet dan jijzelf...
er zijn geen registers in java bytecode, alleen een stack >:)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: ik deel je mening ten dele (mooie zin is dat ;))
Zullen we in de politiek gaan? ;) .
bij het bytecode maken wil je zelf (handmatig) aan gaan geven wat in registers moet? dat lijkt me niet handig want ik denk dat de JVM beter weet wat erin moet dan jijzelf...
Nee joh, natuurlijk niet handmatig... Ik wil bytecode constructies voor het aangeven wat in registers kan. Deze analyse wordt gedaan door de compiler...
bij het bytecode maken wil je de compiler alvast laten uitzoeken wat handig in registers kan? lijkt me wederom niet erg handig want het is echt *heel* platform afhankelijk wat er wel en niet in registers moet
Nou ja, ik wil de compiler eigenlijk uit laten zoeken wat absoluut niet in registers kan. Dat is at compile-time mogelijk (uitzoeken of een var escaped of niet). Daarna blijven de andere vars dus over. Deze kunnen in een register gebruikt worden. De (J)VM hoeft zich hier echter niet druk om te maken. Als hij het toch op de stack wil opslaan, zal mij dat een zorg wezen ;) .
en vooral *wanneer* ... dus als jouw bytecode ineens op Motorola moet draaien ipv. IA32, dan kan het best zo zijn dat het toch slimmer is om andere zaken in de registers te hebben op bepaalde momenten, of de volgorde van verwerking in de registers ff te veranderen...
Klopt, maar het is ook niet de bedoeling om at compile time volledige register allocatie te doen. Compilers bestaan vaak uit een behoorlijk aantal componenten. Een behoorlijk standaard component, de semantische analyse voegt vaak precies de gegevens toe die ik beschrijf. Het is later aan de instructie selectie en register allocation om te beslissen wat er daadwerkelijk moet gebeuren. Deze stappen moeten dus at-runtime gebeuren. De Java bytecode bevat dus alleen meer informatie die de JVM kan gebruiken (of niet).
Hier komt trouwens nog bij dat het niet zo is dat bepaalde variabelen op het onderliggende platform continu in registers staan, en andere continu op de stack.
Klopt, maar meestal worden de operaties wel op de registers uitgevoerd. Je hoeft variabelen alleen maar in het geheugen op te nemen als daar concrete redenen voor zijn: een method call die het register kan aanpassen, een tekort aan registers, variabele is te groot voor het register en dergelijke. Over het algemeen worden variabelen die in registers gebruikt kunnen worden alleen in 'noodgevallen' op de stack geplaatst...
Dat zou je de uitwerking van je theorie aanzienlijk vergemakkelijken maar er is een fundamenteel verschil tussen IA32 die (voorzover ik weet) alleen maar kan rekenen in/met de registers, en een JVM die alleen maar rekent in/op de stack (!)
Mwah, dat valt denk ik wel mee. De bytecode van de JVM gaat alleen uit van de stack, maar dat wil toch niet zeggen dat dit ook daadwerkelijk zo gedaan wordt? In principe is de JVM gewoon de back-end van een compiler als er naar native code wordt gecompileerd (voor interpretatie is het natuurlijk weer heel anders...). Het is toch altijd goed om de back-end zoveel mogelijk gegevens te verschaffen?

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


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op vrijdag 16 november 2001 23:06 schreef limoentje het volgende:Een simpel voorbeeld is volgens mij de vergelijking tussen IA32 en de Sun UltraSparc... die laatste heeft veel meer registers voor algemene bewerkingen (add, multiply, ...), terwijl IA32 eigenlijk maar 1 (jawel, één!) register heeft hiervoor (EAX).
das niet waar, er zijn heel wat meer algemene registers naast EAX.
Hierbij laat ik SSE/SSE2/MMX even buiten beschouwing omdat ik daar (nog) geen kaas van gegeten heb :)
sse en mmx hebben aparte registers (mm0..mm7 en xmm0..xmm7), maar dat zijn eigenlijk gewoon de floating point registers.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: Samenvattend: het is niet handig om de bytecode al register-georienteerd te maken omdat de verschillende CPU's (en de bijbehorende registerverwerking) gewoon niet gelijk werken...
Maar dat is ook niet de bedoeling ;). Het idee is gewoon het toevoegen van extra semantische informatie, niet het vastleggen van een bepaalde toewijzing van variabelen aan registers :) .
En believe me, als het mogelijk was had Sun het al lang gedaan, met als belangrijkste reden natuurlijk de snelheid van uitvoering op hun JVM...
Mwah, Sun is ook niet perfect en zeker niet in het ontwerp van Java bytecode. Grondige aanpassingen daarin worden sowieso al niet gedaan. Het is overigens best mogelijk dat wat ik loop te verkondigen allang gedaan wordt door middel van de attributen in de bytecode...
Een simpel voorbeeld is volgens mij de vergelijking tussen IA32 en de Sun UltraSparc... die laatste heeft veel meer registers voor algemene bewerkingen (add, multiply, ...), terwijl IA32 eigenlijk maar 1 (jawel, één!) register heeft hiervoor (EAX).
Idd er bestaan natuurlijk ontzettend veel verschillen tussen architecturen (neem alleen maar eens het verschil tussen operaties op 2 versus 3 registers, maar dat is ook de taak van de JVM. De compiler (de front-end) geeft slechts aan wat de mogelijkheden zijn... Register-allocatie is een probleem van de JVM...
edit:
heb m'n text nog iets genuanceerd
en uitgebreid ;) .

De link met de topic titel is ondertussen overigens wel heel erg ver te zoeken :o .

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


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hum, misschien een beetje een brutale vraag:
Is het mogelijk om een nieuwe topic aan te maken en de reacties uit dit topic die van toepassing zijn op onderwerp 2 daarheen te moven? Misschien dat er dan iets meer/andere mensen naar kijken...

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


  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

hmmm we zijn een beetje uitgediscusieerd hierover dus van mij hoeft er geen nieuwe topic voor geopend te worden :)

En nog ff voor marcusk:

1) Lees het topic ff door, dan had je ook kunnen lezen dat ik al enkele posts eerder gezegd heb dat een JVM geen registers heeft. Het gaat hier dan ook niet om de registers van de JVM maar om die van het onderliggende platform

2) Noem jij dan eens wat meer registers van IA32 op waarin je algemeen kunt rekenen? Je kunt zoiezo al EBX/ECX/EDX etc. erbuiten laten. Op zich zijn die registers wel allemaal te gebruiken maar er zijn *zat* instructies die alleen op EAX gebruikt kunnen worden...

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
limoentje: hmmm we zijn een beetje uitgediscusieerd hierover dus van mij hoeft er geen nieuwe topic voor geopend te worden :)
hum ja, wel jammer. Begon het net leuk te vinden ;) . Een nieuw topic aanmaken was trouwens vrij lastig, daarom dus de rename (dankzij ACM).

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


  • roelio
  • Registratie: Februari 2001
  • Niet online

roelio

fruitig, en fris.

gooi dan ff een nieuwe vraag of flame of whatever op, want ik voel me een beetje uitgediscussieerd behalve over de posts van marcusk dan :)

AMD Phenom II X4 // 8 GB DDR2 // SAMSUNG 830 SSD // 840 EVO SSD // Daar is Sinterklaas alweer!!


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Beetje off-topic weer, maar wel leuk en over bytecode:

Ik liep net tegen BCEL (Byte Code Engineering Library) aan bij Apache's Jakarta project. Ik wist wel vaag van het bestaan, maar had er nog nooit concreet naar gekeken.

Een kleine quote:
Since Java classes are compiled into portable binary class files (called byte code), it is the most convenient and platform-independent way to implement these improvements not by writing a new compiler or changing the JVM, but by transforming the byte code. These transformations can either be performed after compile-time, or at load-time. Many programmers are doing this by implementing their own specialized byte code manipulation tools, which are, however, restricted in the range of their re-usability.

To deal with the necessary class file transformations, we introduce an API that helps developers to conveniently implement their transformations.

Because the target language of Java is an interpreted language with a small and easy-to-understand set of instructions (the byte code), developers can implement and test their concepts in a very elegant way. One can write a plug-in replacement for the system's class loader which is responsible for dynamically loading class files at run-time and passing the byte code to the Virtual Machine (see section ). Class loaders may thus be used to intercept the loading process and transform classes before they get actually executed by the JVM []. While the original class files always remain unaltered, the behavior of the class loader may be reconfigured for every execution or instrumented dynamically.

The BCEL API (Byte Code Engineering Library), formerly known as JavaClass, is a toolkit for the static analysis and dynamic creation or transformation of Java class files. It enables developers to implement the desired features on a high level of abstraction without handling all the internal details of the Java class file format and thus re-inventing the wheel every time. BCEL is written entirely in Java and freely available under the terms of the Apache Software License.
De manual is erg leuk om te lezen en goed geschreven :) . Het laatste voorbeeld over geparameterizeerde typen in de manual is ook erg leuk :) .

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


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op zaterdag 17 november 2001 09:44 schreef limoentje het volgende:
1) Lees het topic ff door, dan had je ook kunnen lezen dat ik al enkele posts eerder gezegd heb dat een JVM geen registers heeft. Het gaat hier dan ook niet om de registers van de JVM maar om die van het onderliggende platform
excuses, ik had het topic idd niet zo goed doorgelezen
2) Noem jij dan eens wat meer registers van IA32 op waarin je algemeen kunt rekenen? Je kunt zoiezo al EBX/ECX/EDX etc. erbuiten laten. Op zich zijn die registers wel allemaal te gebruiken maar er zijn *zat* instructies die alleen op EAX gebruikt kunnen worden...
tja... als je het zo bekijkt... maar ik vind niet dat je dan kan zeggen dat EBX, ECX en EDX geen general purpose registers zijn.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zaterdag 17 november 2001 09:50 schreef mbravenboer het volgende:
hum ja, wel jammer. Begon het net leuk te vinden ;) . Een nieuw topic aanmaken was trouwens vrij lastig, daarom dus de rename (dankzij ACM).
Tsja, dan had ik alle posts "handmatig" in de DB moeten verhuizen ;)

Gegarandeerd dat ik gisteravond dan iets als "update message set topic=#nieuweid#" en dan enter had gedaan ;)

Dus zonder de "where id=#messageid#" ofzo :P
Pagina: 1