1. #1
    Avatar von Nuebel
    Registriert seit
    23.11.2013
    Beiträge
    446
    Thanked 361 Times in 236 Posts

    Standard Performance Java und C

    Tag,

    ich habe einen naiven Ansatz, um alle Primzahlen unter einer gegebenen Grenze zu ermitteln, jeweils in C und in Java implementiert. Mir ist bekannt, dass es schnellere Verfahren für Primzahlen gibt, darum geht es mir hier aber nicht.

    Hier sind die Programme:

    Spoiler:Java


    import java.math.*;

    import java.util.List;
    import java.util.ArrayList;

    public class Prime {

    public static void main(String[] args) {
    int limit = 100_000;

    long start = System.currentTimeMillis();
    List<Integer> primes = getPrimesBelow(limit);
    long end = System.currentTimeMillis();

    float delta = (float) (end - start) / 1000.0f;

    /*for (int prime : primes) {
    System.out.printf("%09d\t", prime);
    }*/

    System.out.printf("\nEs gibt %d Primzahlen unter %d.\n", primes.size(), limit);
    System.out.printf("Es hat %.2f Sekunden gedauert.\n", delta);
    }


    public static boolean isPrime(int number) {
    if (number <= 1) {
    return false;
    }

    for (int i = 2; i < (int) Math.sqrt(number) + 1; ++i) {
    if (number % i == 0) {
    return false;
    }
    }

    return true;
    }


    public static List<Integer> getPrimesBelow(int limit) {
    List<Integer> primes = new ArrayList<>();

    int candidate = 2;

    while (candidate < limit) {
    if (isPrime(candidate)) {
    primes.add(candidate);
    }

    ++candidate;
    }

    return primes;
    }

    }



    Spoiler:C

    Reallokationsfaktor 2:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <assert.h>
    #include <math.h>

    #include <sys/time.h>


    bool is_prime (int);
    int * get_primes_below (int, int * );


    int main(int argc, char * argv[])
    {
    int limit = 100000;
    int count = 0;

    clock_t begin = clock();
    int * primes = get_primes_below(limit, &count);
    clock_t end = clock();

    float delta = (float) (end - begin) / CLOCKS_PER_SEC;

    /*for (int i = 0; i < count; ++i) {
    printf("%09d\t", primes[i]);
    }*/

    printf("\nEs gibt %d Primzahlen unter %d.\n", count, limit);
    printf("Es hat %.2f Sekunden gebraucht.\n", delta);

    free(primes);

    return EXIT_SUCCESS;
    }


    bool is_prime(int number)
    {
    if (number <= 1) {
    return false;
    }

    for (int i = 2; i < (int) sqrtf(number) + 1; ++i) {
    if (number % i == 0) {
    return false;
    }
    }

    return true;
    }


    int * get_primes_below(int limit, int * count)
    {
    assert(limit > 2);
    assert(NULL != count);

    int allocated = 1;
    int * primes = malloc(allocated * sizeof(int));
    assert(NULL != primes);

    *count = 0;

    int candidate = 2;

    while (candidate < limit) {
    if (*count == allocated) {
    allocated *= 2;
    primes = realloc(primes, allocated * sizeof(int));
    assert(NULL != primes);
    }

    if (is_prime(candidate)) {
    primes[*count] = candidate;
    ++(*count);
    }

    ++candidate;
    }

    return primes;
    }



    Reallokationsfaktor 1.5:

    int * get_primes_below(int limit, int * count)
    {
    assert(limit > 2);
    assert(NULL != count);

    int allocated = 3; // <----------------------
    int * primes = malloc(allocated * sizeof(int));
    assert(NULL != primes);

    *count = 0;

    int candidate = 2;

    while (candidate < limit) {
    if (*count == allocated) {
    allocated = ceil(allocated * 1.5); // <---------------------
    primes = realloc(primes, allocated * sizeof(int));
    assert(NULL != primes);
    }

    if (is_prime(candidate)) {
    primes[*count] = candidate;
    ++(*count);
    }

    ++candidate;
    }

    return primes;
    }



    In der Java API Dokumentation zur ArrayList heißt es:
    As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
    Aus diesem Grund habe ich zwei Versionen des C-Programms geschrieben mit den üblichen Reallokations-Faktoren 1.5 und 2. Kompiliert wurde mit gcc -Wall -std=c99 -O3.

    Ergebnis:
    Limit Primzahlen Java C (Faktor 2) C (Faktor 1.5
    100.000.000 5.761.455 126,08s 321,68s 322,22s
    10.000.000 664.579 4,80s 12,12s 12,09s
    1.000.000 78.498 0,19s 0,48s 0.48s
    100.000 9.592 0,01s 0,02s 0.02s

    Ich bin, wenn überhaupt, nur ein durchschnittlicher Programmierer, also überrascht es mich nicht wirklich, dass ich es nicht schaffe, ein Programm in C zu schreiben, das schneller als sein Java-Pendant läuft. Mich würde aber interessieren, wer von euch es schafft, und wie das C-Programm und die gesetzten Flags des Compilers aussehen, ohne einen anderen Algorithmus für die Primzahlen zu verwenden.

  2. The Following 2 Users Say Thank You to Nuebel For This Useful Post:

    Open Thought (09.03.2015), Sky.NET (10.03.2015)

  3. #2
    Avatar von Snees
    Registriert seit
    18.11.2011
    Beiträge
    1.001
    Thanked 590 Times in 319 Posts

    Standard AW: Performance Java und C

    Hatte gerade mal Lust das Ganze in C#.NET und PHP auszuprobieren. Die Ergebnisse sind auf meinem komischen Arbeitsrechner leider nicht so überragend

    Limit Primzahlen C#.NET PHP
    100.000.000 5.761.455 716,531s n/a
    10.000.000 664.579 26,136s 254,823s
    1.000.000 78.498 1,031s 9,869s
    100.000 9.592 0,048s 0,392s

    Spoiler: Source in C#.NET


    using System;
    namespace Prime
    {
    class Program
    {
    static void Main(string[] args)
    {
    int count = 0;
    long start = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
    long testNumber = 1000000;
    for (long i = 1; i <= testNumber; i++)
    if (IsPrimeNumber(i)) count++;
    long end = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
    long ergebnis = end - start;
    Console.WriteLine("Limit: {0}\nAnzahl: {1}\nZeit in ms: {2}",testNumber.ToString(), count.ToString(), ergebnis.ToString());
    Console.ReadLine();
    }
    static bool IsPrimeNumber(long testNumber)
    {
    if (testNumber % 2 == 0) return false;
    long upperBorder = (long)System.Math.Round(System.Math.Sqrt(testNumber), 0);
    for (long i = 3; i <= upperBorder; i = i + 2)
    if (testNumber % i == 0) return false;
    return true;
    }
    }
    }



    Spoiler:Source in PHP

    PHP-Code:
    <?php
    set_time_limit
    (0);
    ini_set('memory_limit''512M');

    $count 0;
    $start microtime_float();
    $max 10000000;
    for(
    $i 2$i <= $max$i++){
        if(
    isprime($i)){
            
    $count++;
        }
    }
    $ende microtime_float();
    $ergebnis number_format($ende $start3',''.');

    echo 
    $count ' Primzahlen in ' $ergebnis ' Sekunden berechnet.';

    function 
    isprime($primetest) {
        
    $maxtest sqrt($primetest);
        for (
    $i 2$i <= $maxtest; ++$i) {
            if (
    $primetest $i == 0) {
                    return 
    false;
            }
        }
        return 
    true;
    }
    function 
    microtime_float(){
        list(
    $usec$sec) = explode(" "microtime());
        return ((float)
    $usec + (float)$sec);
    }
    ?>
    Geändert von Snees (04.03.2015 um 16:19 Uhr) Grund: PHP ergänzt

  4. The Following User Says Thank You to Snees For This Useful Post:

    Sky.NET (10.03.2015)

  5. #3

    Registriert seit
    01.03.2013
    Beiträge
    48
    Thanked 5 Times in 3 Posts

    Standard AW: Performance Java und C

    Also ich selbst bin zwar quasi vom Fach (Anwendungsentwickler) aber habe mich da noch nicht so 100% mit beschäftigt und würde mich da wohl erst in ein paar Jahren (nach meinem Studium) qualifiziert genug fühlen um darauf eine gute Antwort geben zu können.
    Aber alles in allem gilt für mich immer noch das ein guter Programmcode in C/C++/C# schneller läuft als in Java. Der Grund dafür, Java versucht ein schweizer Taschenmesser zu sein. Soll heißen, es läuft auf "jedem" system, aber auch wenn dein taschenmesser eine säge hat, wirst du damit keine Bäume fellen und ein Floss draus bauen können.
    Java ist so darauf versessen überall zu funktionieren das es zwar genau das tut, aber eben auch nur das. Es "funktioniert" eben. Wie gut ist da die andere Frage.

    Gruß: Sanrasaa

  6. #4
    Avatar von Gameboy9
    Registriert seit
    23.03.2014
    Beiträge
    144
    Thanked 99 Times in 33 Posts

    Standard AW: Performance Java und C

    Warum tust du es dann?
    Ein richtig guter C/C++ programmierer wird sein Programm immer ressourcensparender hinbekommen wie C#, geschweige denn Java. Besonders Java ist ein Monster was Ressourcen angeht, C# geht ja noch.
    Das ist nichts worüber man diskutieren muss oder Meinungen haben kann, denn es ist eine Tatsache! Schau dir z.B. Robotik/Mikrocontroller an, da wird fast ausschließlich C und Assembler eingesetzt weil es dort auf Schnelligkeit ankommt. Entwickelt man ein Fertigsystem geht es auch um Geld. Braucht man mehr Speicher wird ein größerer Chip nötig, der kostet dann ein paar Cent mehr. Klingt nicht viel aber dadurch wird der Endpreis teurer oder das geht sogar vom Gewinn ab. Ist ja auch kein Wunder, bei Java/c# kommt eine weitere Schicht dazu die es dort nicht gibt. Gegenüber Assembler fallen sogar 2 weg.

    Aber durch die Frameworks wird halt vieles einfacher und die Programme laufen auf allen wichtigen Betriebssystemen. Wenn man bedenkt dass selbst Office Kisten heutzutage 2 Kerne und mindestens 4Gig Ram haben, ist weniger Aufwand und mehr Flexibilität höher zu gewichten ob das Programm ein paar MB mehr oder weniger Ram braucht. Außerdem brauchst du einen sehr guten und erfahrenen Programmierer, der auch ordentlich Zeit aufwenden muss für die Optimierungen und teilweise prozessorspezifische Flags setzen muss! Einfach drauf los programmieren machts nicht schneller. Sieht man ja bei Nuebel wie sein C Progrämmchen sogar langsamer ist als Java, weil der compiler besser automatisch optimiert wie er, weil ihm halt die Erfahrung und das Fachwissen fehlt.
    Man braucht viel Ahnung um Leistung rauskitzeln zu können. Hab das mit Webservern auch schon gesehen als ich als Neuling einen nginx aufsetzen wollte weil der ja besonders performant sein soll. Wirklich schneller als der Apache lief er aber nicht. Nachdem ein Kollege der sich seit einigen Jahren intensiver damit beschäftigt kurz davor saß, ging das Teil ab wie Schmids Katze

    Stell dir das bei Software wie Jdownloader oder Minecraft vor die auf 9287349823 verschiedenen Systemen laufen sollen. Dazu noch Windows/Linux. Unfassbar viel Aufwand, das würde sich nicht lohnen.
    Snees Benchmark ist übrigens für die Katz weil die Implementierungen in den Sprachen verschieden sind und außerdem in .NET ineffizient gecastet wird, 'as' ist performanter! Hat mich schon gewundert dass .NET so lahm sein soll obwohl es meiner Erfahrung nach eher schneller als Java ist, das dürfte mit vernünftigem Code sicher besser sein, da beide Sprachen von der Architektur vergleichbar sind.

  7. #5
    Avatar von Nuebel
    Registriert seit
    23.11.2013
    Beiträge
    446
    Thanked 361 Times in 236 Posts

    Standard AW: Performance Java und C

    Zitat Zitat von Sanrasaa
    Aber alles in allem gilt für mich immer noch das ein guter Programmcode in C/C++/(C#) schneller läuft als in Java.
    C# habe ich mal eingeklammert wegen der offensichtlichen Gemeinsamkeit mit Java. Ansonsten gebe ich dir Recht. Aber ich finde es sehr schwierig, guten C- oder C++-Code zu schreiben (ohne große Einbußen an Übersichtlichkeit), der den Optimierungen und der Just-in-time-Kompilierung von Java überlegen ist.

    Zum Beispiel im Eingangspost die Programme mit der Primzahlbestimmung unter einer gegeben Grenze. Unter der Grenze 100.000.000 gibt es 5.761.455 Primzahlen, die in einem Array gespeichert werden. Das Java-Programm wurde damit 195,6 Sekunden früher fertig als das C-Programm. "Um sicherzustellen", dass die Java-ArrayList das tut, was auch im C-Programm geschieht (wenn Größe gleich Kapazität, dann verdopple Kapazität), habe ich die ArrayList durch eine eigene Klasse ersetzt:

    class DynamicArray<T> {
    private static final int reallocFactor = 2;

    private Object[] data;
    private int capacity;
    private int size;

    public DynamicArray(int initialCapacity) {
    capacity = initialCapacity;
    data = new Object[capacity];
    size = 0;
    }

    public DynamicArray() { this(1); }

    public void add(T object) {
    if (size == capacity) {
    extendArray();
    }
    data[size] = object;
    ++size;
    }

    @SuppressWarnings("unchecked")
    public T get(int index) {
    return (T) data[index];
    }

    public int capacity() { return capacity; }
    public int size() { return size; }

    private void extendArray() {
    capacity *= reallocFactor;

    Object[] tmp = new Object[capacity];
    for (int i = 0; i < size; ++i) {
    tmp[i] = data[i];
    }

    data = tmp;
    }
    }

    überraschender Weise war das sogar noch ein Tickchen schneller als die ArrayList aus der Standardbibliothek.

    Wie bereits im Eingangspost erwähnt, wäre ich dankbar, wenn ein pfiffiger C/C++-Programmierer seinen performanten Code hier vorstellen würde. Ich schaff's nicht.

  8. #6
    Avatar von Snees
    Registriert seit
    18.11.2011
    Beiträge
    1.001
    Thanked 590 Times in 319 Posts

    Standard AW: Performance Java und C

    Zitat Zitat von Gameboy9 Beitrag anzeigen
    Snees Benchmark ist übrigens für die Katz weil die Implementierungen in den Sprachen verschieden sind und außerdem in .NET ineffizient gecastet wird, 'as' ist performanter! Hat mich schon gewundert dass .NET so lahm sein soll obwohl es meiner Erfahrung nach eher schneller als Java ist, das dürfte mit vernünftigem Code sicher besser sein, da beide Sprachen von der Architektur vergleichbar sind.
    Es wäre interessant deine Umsetzung für die Berechnung in C# zu sehen. Ich bin kein C#-Profi und mache das nur als Hobby nebenbei daher wäre es interessant für mich zu sehen wie du das lösen würdest.

  9. #7
    Avatar von patlux
    Registriert seit
    26.10.2011
    Beiträge
    1.195
    Thanked 1.596 Times in 725 Posts
    Blog Entries
    2

    Standard AW: Performance Java und C

    Zitat Zitat von Sanrasaa Beitrag anzeigen
    Java versucht ein schweizer Taschenmesser zu sein. Soll heißen, es läuft auf "jedem" system,
    C(++) läuft auch auf jedem System.

    --

    Bei mir sieht das Ergebnis etwas anders aus:


Ähnliche Themen

  1. Abends erhebliche Performance-Probleme auf Youtube
    Von Casper <3 im Forum Internet und Technik
    Antworten: 17
    Letzter Beitrag: 23.02.2015, 22:04
  2. Antworten: 13
    Letzter Beitrag: 23.03.2014, 01:35
  3. Antworten: 8
    Letzter Beitrag: 02.12.2013, 23:41
  4. Debian Squeeze & Apache2, Performance verbessern und absichern
    Von Snees im Forum Server-Administration
    Antworten: 13
    Letzter Beitrag: 03.07.2013, 16:08
  5. ASRock Fatal1ty P67 Performance - gut oder anderes?
    Von Devon im Forum Kaufberatung
    Antworten: 1
    Letzter Beitrag: 06.01.2013, 19:12
Diese Seite nutzt Cookies, um das Nutzererlebnis zu verbessern. Klicken Sie hier, um das Cookie-Tracking zu deaktivieren.