# CPU nicht ausgelastet



## CK (18. Nov 2008)

Hallo mein System ist ein:
XP Pro SP2Core 2 Duo E6850 3 GB RAM.
Java 1.5.

Jetzt habe ich eine Anwendung die relativ komplexe Operationen auf DOM-Bämen macht.
Um die Geschwindigkeit zu steigern werden mehrere Files  in Threads bearbeitet.
Sagen wir mal acht. Um dies sicher zu stellen benutze ich einen Thread Executor.


```
threadExecutor = Executors.newFixedThreadPool(8);
```

Nun zu meinen Problem:
Da ich ja soviel Leistung wie möglich rausholen will, wäre es ja sinnvoll wenn die CPU voll ausgelastet
ist. Dies ist aber nicht der Fall. Auslastung liegt immer so bei 50-60%.
Durch ein Profiling weis ich das die Thread nicht geblockt sind und auch keine Sleeps sich
innerhalb dieser Threads befindet.
Bin da recht überfragt warum das Programm nicht die gesamte CPU-Last anzieht.

Bitte um euere Hilfe.


----------



## Capasso (18. Nov 2008)

Hast du mal beobachtet wie sich das verhält wenn du mehr oder weniger Threads machst.

Evtl. liegt es am Plattenzugriff, sofern du du oft von Festplatte liest oder darauf schreibst


----------



## CK (18. Nov 2008)

Hab die Anzahl der Threads auf 4 gesetzt . Das halbiert ja dann die Plattenzugriffe. Hat aber leider auch nix geändert. Also scheint die Anzahl der Threads nix auszumachen.
Haste vielleicht noch ne Andere Idee?


----------



## didjitalist (18. Nov 2008)

als erstes solltest du aber deinen profiler mal darauf ansetzen, womit tatsächlich die meiste zeit verbracht wird. womöglich hilft es schon, wenn die dateien erstmal alle sequentiell vollständig eingelesen werden und nur das reine parsing in threads ausgelagert wird.


----------



## FArt (18. Nov 2008)

Die CPU ist zu 50%-60% voll ausgelastet... ist das über beide Kerne die gemittelte Auslastung?

Vermutung: die Threads laufen alle auf dem gleichen Kern und lasten diesen voll aus.
Ob das auch anders geht, hängt sicher von der Runtime und dem Betriebssystem ab.


----------



## CK (18. Nov 2008)

Habs mal gecheckt, die Kerne sind ca. gleich ausgelastet.


----------



## SlaterB (18. Nov 2008)

erstelle dir doch vergleichsweise ein Programm, welches in 8 Threads nur CPU-Aufgaben erledigt, 
wie dauerhaft sinnlos Schleifen zu durchlaufen und mathematische Operationen durchzuführen


----------



## CK (18. Nov 2008)

Hab mal eben sowas getestet:

```
public static void main(String[] args)
    {
        Executor exec = Executors.newFixedThreadPool(8);

        for (int i = 0; i < 8; i++)
        {
            // sinnloser Thread
            Thread t = new Thread(new Runnable()
            {
                public void run()
                {
                    while (1 == 1)
                    {
                        int ergebniss = 1000 * 1000 * 1000;
                        Math.pow(1000, ergebniss);
                    }
                }
            });

            exec.execute(t);
        }

    }
```
Dabei geht die CPU sofort auf 100%.
Bis langsam echt überfragt was das sein kann.


----------



## FArt (18. Nov 2008)

Das bestätigt die Theorie, dass das Bottleneck nicht in der CPU Auslastung zu suchen ist.

Da hilft nur ein Monitoring Tool und/oder ein Profiler, Kontrolle aller Ressourcen (IO, Netzwerk, ...) und die Kontrolle der Synchronisation. Evtl. müssen die Threads zu oft aufeinander warten.


----------



## CK (18. Nov 2008)

Danke für die Antwort. Wie ich schon zu Anfang geschrieben hatte habe ich mit einem Profiler alle Threads untersucht, aber die sind wärend der gesamten Laufzeit auf Running, kein Waiting, kein Blocking.

Zu den Ressourcen:
Die Files liegen alle im selben Verzeichniss, sind aber für jeden Thread ein anderes File.
Die Threads loggen alle ins selbe File.
Netzwerkverbindung wird nicht genutzt.


----------



## jago (18. Nov 2008)

CK hat gesagt.:
			
		

> Danke für die Antwort. Wie ich schon zu Anfang geschrieben hatte habe ich mit einem Profiler alle Threads untersucht, aber die sind wärend der gesamten Laufzeit auf Running, kein Waiting, kein Blocking.
> 
> Zu den Ressourcen:
> Die Files liegen alle im selben Verzeichniss, sind aber für jeden Thread ein anderes File.
> ...



Ganz wilder guess - ist es vielleicht ein Problem mit beschraenktem Ram? Wenn nicht genug Ram da ist laeuft GC praktisch pausenlos - und das GC haelt alle Threads an abwohl es wohl der Profiler nicht anzeigt.

Klingt unwahrscheinlich - vor allem weil es wohl auch eine OutOfMemException gegeben haetter - aber versuch doch einfach mal -Xmx512M

Gruss,
jago


----------



## FArt (18. Nov 2008)

jago hat gesagt.:
			
		

> CK hat gesagt.:
> 
> 
> 
> ...



Klingt nicht so unwahrscheinlich. Allerdings hat ja ein Profiling keine Auffälligkeiten ergeben (die Zeiten des GC jeder Generation kann man ja auch schön ansehen). Allerdings glaube ich persönlich diesem Profiling nicht...


----------



## Gast (18. Nov 2008)

>> Die Threads loggen alle ins selbe File. 

Lass das Logging doch mal weg.


----------



## Ark (18. Nov 2008)

Festplatten sind laaaaaaangsam ... und lassen die CPU warten.  Vielleicht ist es günstiger, immer nur eine Datei nach der anderen abzuarbeiten!? Wenn man versucht, mehrere Dateien gleichzeitig anzusprechen, könnte es wohl passieren, dass sich der R/W-Kopf der Platte jedes Mal neu positionieren muss; man ahmt quasi stark fragmentierte Dateien nach.

Möglicherweise täusche ich mich gerade, aber so würde ich mir jetzt das Phänomen erklären.

Ark


----------



## SlaterB (18. Nov 2008)

weiter ausgemalt:
nur ein Thread sollte (im Voraus) Dateien einlesen, wegschreiben und vielleicht ab und zu (nicht bei jedem Eintrag) Log schreiben,
je nach Auftrag von anderen Threads,

die anderen bearbeiten nur die vorhandenen Daten,
wenn sie damit schneller sind als der Einlesethread neue heranschaffen und Ergebnisse wegschreiben kann,
dann ist das ok, dann ist eben die CPU schneller als die Festplatte und darf sich dafür auch die ein oder andere Pause gönnen


----------



## CK (19. Nov 2008)

Vermute auch stark das es an den Platten liegt, aber immer nur eine Datei abzuarbeiten wäre noch viel langsamer. Hatte es mal ausprobiert. Bei den Operationen die ich durchführe dauert es mit mehreren thread bei 400 Files ca. 20 Minuten und mit einem ca. 2 Std.
Naja werde ich wohl mit der Einbusung leben müssen. Trotzdem Danke.


----------



## FArt (19. Nov 2008)

CK hat gesagt.:
			
		

> Vermute auch stark das es an den Platten liegt, aber immer nur eine Datei abzuarbeiten wäre noch viel langsamer. Hatte es mal ausprobiert. Bei den Operationen die ich durchführe dauert es mit mehreren thread bei 400 Files ca. 20 Minuten und mit einem ca. 2 Std.
> Naja werde ich wohl mit der Einbusung leben müssen. Trotzdem Danke.



Wenn du nur Vermutungen anstellst, wirst du durch Zufall eine Verbesserung herbeiführen oder tatsächlich damit leben müssen. Wenn du aber mal dein System (und nicht nur die Applikation mit einem Profiler) monitorst, kannst du zumindest sagen wo das Bottleneck ist... eventuell dann auch überlegen wie man es abstellen kann.

Zur Analyse unter Linux kommt man mit 'top' schon sehr weit. Unter Windows hilft "Process Explorer" als TaskManager-Ersatz schon sehr.


----------



## tuxedo (19. Nov 2008)

Ich versteh das Problem nicht. Ein anständiger Profiler sagt einem genau wo wieviel Zeit verbraten wurde. So lässt das das Problem nahezu auf die Millisekunde genau bestimmern. 

Und ich würde fast meine Hand dafür ins Feuer legen dass es am Logging bzw. dem Plattenzugriff hapert. 

Wenn viel geloggt wird: Bist du dir sicher dass du nicht massenweise String-Konkatenation verwendest? Ist so ein typischer "Fehler" beim loggen. Loggen an sich kostet auch einiges an Zeit. Und wenn du's abschaltest (via Config) und den Fehler mit der Konkatenation begangen hast, bremst es natürlich trotzdem.

- Alex


----------



## SlaterB (19. Nov 2008)

String-Konkatenation dürfte auch die CPU auslasten oder?
falsche Richtung


----------



## tuxedo (19. Nov 2008)

ach ja, schei**e ...  Genau falsch herum gedacht ... *mist* Ist halt noch zu früh am morgen ;-)

Naja, nichts desto trotz: Ein Profiler sagt einem extrem genau wo das Bottleneck zu suchen ist.

- Alex


----------



## FArt (19. Nov 2008)

Ob Plattenauslastung an sich das Problem ist, sieht man beim Monitoring, indem man sich die I/O Paramter (R/W/O) ansieht, ist die Lösung. Dann gilt es nur noch herauszufinden, wer den Traffic verursacht, denn das Problem muss nicht durch die eigene Applikation allein verursacht werden.

Beispiel: Logging in Files kann natürlich den IO entsprechend erhöhen. Wenn das aber im Regelfall unkritisch ist, parallel dazu aber anderweitig IO-Aktivitäten stattfinden, ist an sich nicht das Logging schuld.


----------

