Αλλαγή γραμματοσειράς
Ημερομηνία Τετ Οκτ 23, 2019 6:22 am
foss.aueb.gr

Προγραμματισμός

Απλό Java/C benchmark

Σχετικά με τον προγραμματισμό

Απλό Java/C benchmark

Δημοσίευσηαπό cyberpython » Τετ Δεκ 15, 2010 10:43 pm

Ήθελα να δω τη διαφορά στην ταχύτητα εκτέλεσης απλών υπολογισμών ανάμεσα σε C με το GCC και Java (= πόσο πιο αργή είναι η Java από τη C) και αποφάσισα να γράψω ένα απλό πρόγραμμα που θα υπολογίζει την ακολουθία fibonacci μέχρι ένα συγκεκριμένο N σε C και το ίδιο πρόγραμμα σε Java.

Το αποτέλεσμα με εξέπληξε, αφού η Java φαίνεται να είναι (αρκετά) ταχύτερη!

Εικόνα

GCC version: gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Javac version: javac 1.6.0_22
Java version: java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Server VM (build 17.1-b03, mixed mode)

Ρίξτε και εσείς μια ματιά μήπως κάνω κάποιο λάθος (π.χ. στη μέτρηση του χρόνου εκτέλεσης με την clock_gettime):

benchmark.c (compile με gcc -o benchmark.bin benchmark.c -lrt)
Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ITERATIVE_N 1000000
#define RECURSIVE_N 35
#define NUM_OF_TESTS 100

long long diff( struct timespec start, struct timespec end) {
    /*
     * Adapted from code by Guy Rutenberg ( http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/ )
     * Creative Commons Attribution-Noncommercial-Share Alike 2.5 Israel License.
     */
    struct timespec result;
    if ((end.tv_nsec - start.tv_nsec) < 0) {
        result.tv_sec = end.tv_sec - start.tv_sec - 1;
        result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
    } else {
        result.tv_sec = end.tv_sec - start.tv_sec;
        result.tv_nsec = end.tv_nsec - start.tv_nsec;
    }
    return result.tv_sec*1000000000+result.tv_nsec;
}

long long fibonacciIterative() {
    struct timespec tp1;
    struct timespec tp2;

    clock_gettime(CLOCK_REALTIME, &tp1);

    int a = 1;
    int b = 1;
    int c;
    int i;
    for (i = 3; i <= ITERATIVE_N; i++) {
        c = a + b;
        a = b;
        b = c;
    }

    clock_gettime(CLOCK_REALTIME, &tp2);
    long nsec = diff(tp1, tp2);
    return nsec;
}

int fib(int n) {
    if (n <= 2) {
        return 1;
    } else {
        return fib(n - 1) + fib(n - 2);
    }
}

long long fibonacciRecursive() {
    struct timespec tp1;
    struct timespec tp2;

    clock_gettime(CLOCK_REALTIME, &tp1);

    fib(RECURSIVE_N);

    clock_gettime(CLOCK_REALTIME, &tp2);
    long nsec = diff(tp1, tp2);
    return nsec;
}

int main() {
    long long fibonacciIterativeResults[NUM_OF_TESTS];
    long long fibonacciRecursiveResults[NUM_OF_TESTS];
    int i;

    for (i = 0; i < NUM_OF_TESTS; i++) {
        long long nsec = fibonacciIterative();
        printf("Iterative - Time: %lld nsec\n", nsec);
        fibonacciIterativeResults[i] = nsec;
    }
    printf("\n--------------------------------------------\n\n");

    for (i = 0; i < NUM_OF_TESTS; i++) {
        long long nsec = fibonacciRecursive();
        printf("Recursive - Time: %lld nsec\n", nsec);
        fibonacciRecursiveResults[i] = nsec;
    }
    printf("\n--------------------------------------------\n\n");

   
    FILE *fp = NULL;
    fp = fopen("../results/c_results.csv", "w");
    if (fp != NULL) {
        for (i = 0; i < NUM_OF_TESTS; i++) {
            fprintf(fp, "%lld,%lld\n", fibonacciIterativeResults[i], fibonacciRecursiveResults[i]);
        }
        fclose(fp);
    }

    return (EXIT_SUCCESS);
}




BenchMark.java
Κώδικας: Επιλογή όλων
import java.io.*;

class BenchMark{
    private static int ITERATIVE_N  = 1000000;
    private static int RECURSIVE_N  = 35;
    private static int NUM_OF_TESTS = 100;
       
    private static long fibonacciIterative(){
        long tp1;
        long tp2;

        tp1 = System.nanoTime();
       
        int a = 1;
        int b = 1;
        int c;
        int i;
        for (i = 3; i <= ITERATIVE_N; i++) {
            c = a + b;
            a = b;
            b = c;
        }
                  
        tp2 = System.nanoTime();
        long nsec = tp2 - tp1;
        return nsec;
    }
       
    private static int fib(int n) {
        if (n <= 2) {
            return 1;
        } else {
            return fib(n - 1) + fib(n - 2);
        }
    }
       
    private static long fibonacciRecursive(){
            long tp1;
        long tp2;

        tp1 = System.nanoTime();
       
        fib(RECURSIVE_N);
       
        tp2 = System.nanoTime();
        long nsec = tp2 - tp1;
        return nsec;
    }
       
   public static void main(String[] args){
      long fibonacciIterativeResults[] = new long[NUM_OF_TESTS];
      long fibonacciRecursiveResults[] = new long[NUM_OF_TESTS];
      
        int i = 0;
       
        for (i=0; i<NUM_OF_TESTS; i++){
            long nsec = fibonacciIterative();
            System.out.printf("Time: %1$d nsec\n", nsec);
            fibonacciIterativeResults[i] = nsec;
        }
        System.out.println("\n--------------------------------------------\n");
       
        for (i=0; i<NUM_OF_TESTS; i++){
                long nsec = fibonacciRecursive();
            System.out.printf("Time: %1$d nsec\n", nsec);
            fibonacciRecursiveResults[i] = nsec;
        }
        System.out.println("\n--------------------------------------------\n");
       
       
        try{
                PrintWriter w = new PrintWriter("../results/java_results.csv");
                for (i=0; i<NUM_OF_TESTS; i++){
                        w.format("%1$d,%2$d\n", fibonacciIterativeResults[i], fibonacciRecursiveResults[i]);
                }
                w.flush();
                w.close();
        }catch(Exception e){
                e.printStackTrace();
        }
               
   }
}



Αποτελέσματα:

c_results.csv
Κώδικας: Επιλογή όλων
10055958,155399487
9168869,155949301
6019655,152684535
6900462,151313622
6027148,149167462
6037679,151462015
6014337,151951852
6014339,152259303
6034115,149230276
6042590,151250208
6018276,149067203
6019156,156469463
6014902,152895369
6035189,152043486
6038458,153412931
6016687,151830978
6014593,151831242
6017137,151603582
6033583,150970514
6094451,151666628
6020053,150875492
6016282,150617024
6021636,151723461
6034869,151157623
6034570,151642391
6015646,151975778
6014115,152756594
6022742,155436980
6037780,156123739
6041057,156164268
6013517,154174125
6013766,150574272
6023068,154725452
6035122,153192698
6033339,151894192
6015496,153207008
6019618,154065619
6025175,153097306
6035560,155451296
6037055,154531950
6015102,153103987
6014420,156462504
6025674,155050330
6033358,155585595
6033040,155638593
6093570,150998896
6010931,172606963
6031159,153219333
6025437,152288191
6041800,156867834
6010596,154974526
6019082,152050127
6024917,153697207
6036565,154540255
6029448,155980327
6019427,154812585
6011145,152491272
6037375,151280795
6029448,154478639
6029044,151538496
6011819,152551556
6018067,152878476
6024168,151474569
6044805,153513752
6022836,153777787
6019183,152170356
6010351,151209515
6038974,151752595
6034948,155371459
6023438,152561583
6010096,151388488
6022613,150775438
6023967,150917393
6054307,151568226
6011651,151720834
6018992,150748712
6010990,151929022
6037225,152051468
6036884,154286261
6025823,151706653
6021526,151455387
6017537,152934065
6023297,153605611
6055100,151688557
6011871,152072115
6019113,153580355
6010256,155736122
6038348,156426390
6036234,155502597
6021457,153782623
6015117,149693908
6017901,150161477
6023863,148972581
6053017,153365160
6012226,153533216
6020290,150594316
6010371,151840020
6038666,151377558
6036388,149457793
6020542,152059533



java_results.csv
Κώδικας: Επιλογή όλων
6758807,77269213
39035,66649104
37855,66569468
37665,66570614
37620,66590916
37755,66560009
37790,66553813
505,66547716
470,66567733
505,66571265
465,66597252
465,66547625
480,66537435
505,66533865
480,66560419
475,66528308
480,66622786
510,66573094
485,66527203
480,66549572
486,66581811
510,66538412
480,66533100
480,66536705
481,66640047
515,66607354
485,66599078
485,66740058
480,66685647
510,66559687
550,66582797
485,66612923
485,66882805
510,66696121
490,66678116
480,66625439
490,66637243
485,66538836
485,66904702
480,67770411
480,66713930
520,66549539
485,66546135
485,66554324
480,66540774
520,66527923
485,66607545
485,66525370
480,66600457
495,68731762
485,67116308
485,67006712
485,66818042
490,66821615
480,66558680
485,66420975
485,66535676
515,66573534
480,66625796
480,66556383
485,66480903
515,67050246
515,66992756
480,67139677
480,66748818
490,66473384
515,66424557
540,66404317
480,66446408
490,66446809
480,66431729
480,66399290
485,66400790
515,66921676
480,66416045
486,66435712
485,66568767
515,66434153
485,66418182
515,66434795
485,66454762
525,66425641
485,66434676
485,66442304
485,66464572
515,66461462
510,66562568
480,66702145
480,66533849
510,66512167
485,66542312
485,66544225
485,66497348
515,68013518
485,74004072
485,71152562
485,67367776
510,67224554
480,67433364
485,66923543
Άβαταρ μέλους
cyberpython
Open Member
 
Δημοσ.: 66
Εγγραφη: Τετ Μάιος 20, 2009 10:50 pm
Operating System: Ubuntu

Re: Απλό Java/C benchmark

Δημοσίευσηαπό cypha » Τετ Δεκ 15, 2010 11:05 pm

Δοκιμαζεις μια και με τα optimization options του gcc http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html να δουμε και εκει διαφορα; Π.χ. με -Ο2 η -Ο3
Εικόνα
Άβαταρ μέλους
cypha
Moderator
 
Δημοσ.: 89
Εγγραφη: Τρί Οκτ 27, 2009 12:07 pm
Operating System: Debian lenny, Αrch linux

Re: Απλό Java/C benchmark

Δημοσίευσηαπό cyberpython » Τετ Δεκ 15, 2010 11:22 pm

Με το -O3 βελτιώνονται δραματικά τα αποτελέσματα, στην επαναληπτική μέθοδο η C έχει σημαντικά καλύτερο χρόνο μέχρι την 7η επανάληψη, ενώ στην αναδρομική είναι σταθερά καλύτεροι οι χρόνοι με διαφορά.

Εικόνα

Αποτελέσματα με το διακόπτη -O3:
c_results.csv
Κώδικας: Επιλογή όλων
816,50375892
745,46404598
695,46399886
690,46388124
695,46388391
695,47244383
695,46399747
695,46393794
695,46399198
695,46383613
695,46515877
695,46409339
695,46390708
695,46393670
696,46389806
695,46392311
695,46405795
695,46394226
695,46454494
690,46385123
691,46399028
690,46409739
690,46394944
690,46495009
690,46424080
690,46403015
690,46390110
690,46383165
695,46398291
695,46383432
695,46397892
690,46389159
690,46512380
690,46401528
690,46409277
690,46385253
690,46412294
695,46392466
696,46442931
695,46406143
695,46402702
690,46407591
695,46860660
695,46433431
696,46400980
695,46406758
690,46413304
695,46423674
695,47296468
695,46403468
695,46410322
695,46399195
690,46391391
695,46483911
690,46401737
695,46392687
690,46395193
690,46393101
690,46385400
690,46394276
690,46448626
691,46401112
690,46402456
695,46389933
690,46407414
695,46388124
695,46407531
696,46496151
695,46407311
695,46396210
690,46392912
695,46389767
690,46394726
691,46379913
690,46783578
690,46512122
690,46395346
690,46413946
690,46401773
691,46388696
690,46399601
690,46386514
690,46435903
690,46394170
695,46403521
696,46393811
695,46435635
695,46395881
695,46400816
690,46385543
695,46396917
690,47073298
695,46398482
695,46398825
695,46470332
695,46627857
695,46921474
690,46851428
695,46624241
695,46637529
Άβαταρ μέλους
cyberpython
Open Member
 
Δημοσ.: 66
Εγγραφη: Τετ Μάιος 20, 2009 10:50 pm
Operating System: Ubuntu

Re: Απλό Java/C benchmark

Δημοσίευσηαπό cypha » Τετ Δεκ 15, 2010 11:42 pm

Nice, ωραιο τεστακι. :)
Εικόνα
Άβαταρ μέλους
cypha
Moderator
 
Δημοσ.: 89
Εγγραφη: Τρί Οκτ 27, 2009 12:07 pm
Operating System: Debian lenny, Αrch linux

Re: Απλό Java/C benchmark

Δημοσίευσηαπό HdkiLLeR » Πέμ Δεκ 16, 2010 2:05 am

Και στις δύο περιπτώσεις μετράς χρησιμοποιώντας ένα wall clock. Tο πρόβλημα είναι ότι σε ένα multi-tasking περιβάλλον, περιλαμβάνεις μέσα στην μέτρηση σου όλο το noise απο context switches, interrupt handlings, processes που εκτελούνται στο ενδιάμεσο κλπ. Π.χ. μεταξύ της πρώτης και δεύτερης κλήσης της clock_gettime(), δεν είναι μόνο ο κώδικας που βάζεις ενδιάμεσα (πχ fib()) που θα εκτελεστεί. Στο ενδιάμεσο στην κάρτα δικτύου σου μπορεί να έχουν έρθει 100000 πακέτα, για κάθε ένα απο αυτά το λειτουργικό θα σταματήσει το process (context switch), θα τρέξει κομμάτι του driver της κάρτα σου, θα κάνει ότι άλλο processing χρειάζεται για το dispatching του πακέτου κλπ κλπ. Ομοίως, εάν το process ξεπεράσει το time quantum που του αντιστοιχεί, θα γίνει preempt απο την CPU και κάποιο άλλο process θα τρέξει στο ενδιάμεσο. Υπάρχουν πάρα πολλά πράγματα συνεπώς που συμβαίνουν στο ενδιάμεσο και τα βάζεις μέσα στις μετρήσεις σου. Τέλος είναι "άδικο" να τρέχεις το C version χωρίς optimizations, μιας και ο JIT compiler του JVM κάνει heavily optimize το bytescode πριν το ρίξει σε native x86. Βtw μπορείς να δώσεις λίγο μηχανάκι (CPU) και OS?

Σε γενικές γραμμές, εάν κάνεις σωστά το πείραμα, δεν θα δείς μεγάλες διαφορές για αυτό που μετράς. Η Java πλέον χρησιμοποιεί JIT. Συνεπώς θα κάνει dynamically compile τα bytecodes σε native x86 code, οπότε, και για τα δύο προγράμματα που έχεις γράψει δεν νομίζω ότι ο κώδικας που θα παραχθεί (x86 asm) θα είναι πολύ διαφορετικός (η CPU σου η ίδια είναι, ότι κόλπα θα κάνει ο ένας θα κάνει και ο άλλος compiler). Εκεί που θα δείς ουσιαστικές διαφορές μεταξύ Java και C είναι εάν στρεσάρεις το I/O, process/thread management, etc. Σε αυτά είναι η Java υστερεί...Σε 10 γραμμές κώδικα και οι δύο compilers, πιστεύω, ότι θα κάνουν utilize με τον καλύτερο τρόπο την CPU σου.

ps: εάν παρατηρήσεις τα πρώτα runs έχουν πάντα λίγο discrepancy; αυτό είναι απο τα cache misses...οταν κάνεις micro-benchmarks εάν η cache σου δεν είναι warm, τις μετρήσεις σου δεν τις βάζεις μέσα στο averaging γιατί στην πραγματικότητα είναι outliers.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d-->--- s+:+ a- C++(+++) BILS++++$ P--- L++++>+++++ E--- W+++ N+ o+ K w--
O M+ V-- PS++>+++ PE- Y++ PGP++ t+ 5+ X+ R* tv b++ DI- D+ G+++ e+++>++++ h r++ y++
------END GEEK CODE BLOCK------
Άβαταρ μέλους
HdkiLLeR
Open Member
 
Δημοσ.: 36
Εγγραφη: Παρ Μάιος 15, 2009 2:57 am
Τοποθεσια: Manhattan - New York

Re: Απλό Java/C benchmark

Δημοσίευσηαπό c00kiemon5ter » Πέμ Δεκ 16, 2010 4:24 am

HdkiLLeR έγραψε: Εκεί που θα δείς ουσιαστικές διαφορές μεταξύ Java και C είναι εάν στρεσάρεις το I/O, process/thread management, etc. Σε αυτά είναι η Java υστερεί...Σε 10 γραμμές κώδικα και οι δύο compilers, πιστεύω, ότι θα κάνουν utilize με τον καλύτερο τρόπο την CPU σου.

έχεις κοιτάξει καθόλου για το java.nio πακέτο? Υποτίθεται θα έχει μεγάλες βελτιώσεις σε IO και network/stream operations και θα περιλάβει και τη νέα πιο πλούσια File interface.
Γενικά εκεί που είσαι χρησιμοποιείτε καθόλου Java? Κι αν ναι, τί εφαρμογές έχει ?

cyber τα γραφήματα με τί τα έβγαλες, ωραία χρώματακια έχουν :P
Computers are simple. You just write an instruction and they follow it.
Εικόνα
a cookie! ~ i.will.do.science.to.it! Εικόνα
Άβαταρ μέλους
c00kiemon5ter
cookie hunter
 
Δημοσ.: 554
Εγγραφη: Δευτ Μάιος 11, 2009 1:55 am
Τοποθεσια: (void *)NULL
Operating System: ~ Arch ~ .: Gentoo :.

Re: Απλό Java/C benchmark

Δημοσίευσηαπό HdkiLLeR » Πέμ Δεκ 16, 2010 7:16 am

c00kiemon5ter έγραψε:έχεις κοιτάξει καθόλου για το java.nio πακέτο? Υποτίθεται θα έχει μεγάλες βελτιώσεις σε IO και network/stream operations και θα περιλάβει και τη νέα πιο πλούσια File interface.


Ναι το βάλανε στην 1.4 εάν θυμάμαι καλά. Ουστιαστικά σου δίνει την δυνατότητα να κάνεις Ι/Ο multiplexing, non-blocking I/O, memory-mapped I/O, κλπ -- κοινώς φέρανε την select(2)/poll(2), το equivalent του O_NONBLOCK στην open(2), mmap(2)... Σίγουρα το NIO κάνει πιο σοβαρή την πλατφόρμα (χωρίς αυτό ήταν σαν να ήμασταν στα 60s) αλλά σε κάθε περίπτωση το additional delay που θα έχεις απο reference counting στα objects και απο το garbage collection, θα το πληρώνεις σε throughput, μικρότερο req/sec, etc.

c00kiemon5ter έγραψε:Γενικά εκεί που είσαι χρησιμοποιείτε καθόλου Java? Κι αν ναι, τί εφαρμογές έχει ?


nop :) -- η IBM (απο τις μεγάλες) παίζει με Java κυρίως (websphere)
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d-->--- s+:+ a- C++(+++) BILS++++$ P--- L++++>+++++ E--- W+++ N+ o+ K w--
O M+ V-- PS++>+++ PE- Y++ PGP++ t+ 5+ X+ R* tv b++ DI- D+ G+++ e+++>++++ h r++ y++
------END GEEK CODE BLOCK------
Άβαταρ μέλους
HdkiLLeR
Open Member
 
Δημοσ.: 36
Εγγραφη: Παρ Μάιος 15, 2009 2:57 am
Τοποθεσια: Manhattan - New York

Re: Απλό Java/C benchmark

Δημοσίευσηαπό c00kiemon5ter » Πέμ Δεκ 16, 2010 11:41 am

dammit!

θα κάνω νέο τόπικ αργότερα :problem:
Computers are simple. You just write an instruction and they follow it.
Εικόνα
a cookie! ~ i.will.do.science.to.it! Εικόνα
Άβαταρ μέλους
c00kiemon5ter
cookie hunter
 
Δημοσ.: 554
Εγγραφη: Δευτ Μάιος 11, 2009 1:55 am
Τοποθεσια: (void *)NULL
Operating System: ~ Arch ~ .: Gentoo :.

Re: Απλό Java/C benchmark

Δημοσίευσηαπό cyberpython » Πέμ Δεκ 16, 2010 2:40 pm

HdkiLLeR έγραψε:Βtw μπορείς να δώσεις λίγο μηχανάκι (CPU) και OS?

Intel Core2 4400@2 GHz
2GB DDR2 RAM
Ubuntu 10.10 32-bit (2.6.35-23-generic)

c00kiemon5ter έγραψε:cyber τα γραφήματα με τί τα έβγαλες, ωραία χρώματακια έχουν

OO.o Calc
Άβαταρ μέλους
cyberpython
Open Member
 
Δημοσ.: 66
Εγγραφη: Τετ Μάιος 20, 2009 10:50 pm
Operating System: Ubuntu


Επιστροφή στην Προγραμματισμός

cron
foss.aueb.gr

Μελη σε συνδεση

Συνολικά υπάρχουν 0 μέλη συνδεδεμένα: 0 εγγεγραμμένο, 0 κρυφοί και 0 επισκέπτης (με βάση τα μέλη που έχουν συνδεθεί τα τελευταία 5 λεπτά)
Περισσότερα μέλη σε σύνδεση 167 την Κυρ Οκτ 02, 2016 2:55 am

Μέλη σε αυτή την Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες

Γενέθλια

Κανένα μέλος δεν έχει γενέθλια σήμερα