2013-06-19 15 views
9

Potrzebuję uzyskać czas obliczeniowy niektórych części algorytmu zaimplementowanego w C z NDK/JNI.Jak uzyskać czas obliczeń w NDK

Czytałem to pytanie: Android Get Current timestamp?

myślę, że mogę uzyskać czas obliczeń z rozmowy JNI przy użyciu tej samej metody w ten sposób:

Long start, end, time; 
start = System.currentTimeMillis()/1000; 
//my native call 
end = System.currentTimeMillis()/1000; 
time = end - start; 
Log.i(TAG, "Time ... (ms): " + time); 

ale muszę sprawdzić obliczenia czasy małych części wewnątrz metody natywnej. Jak mogę to zrobić?

+0

możesz to zrobić, ustawiając komunikaty dziennika przed i po metodzie wywołania ... a następnie po prostu użyj time = end - start; Mam na myśli wydrukować czas w logach. – TheFlash

+0

@AllessandroGaietta Twój przykład dzieli 'currentTimeMillis()' przez 1000 ... Czy chcesz, aby twój pomiar był tak samo ważny jak sekundy? – mah

+0

@mah Jest to błąd kopiowania, nie chcę podzielić przez 1000; D –

Odpowiedz

7

z poziomu C/C++ kod,

#include <sys/time.h> 
long long currentTimeInMilliseconds() 
{ 
    struct timeval tv; 
    gettimeofday(&tv, NULL); 
    return ((tv.tv_sec * 1000) + (tv.tv_usec/1000)); 
} 

To będzie Ci strukturę z aktualnym czasem w kilka sekund i mikrosekund, co daje wystarczająco do pomiaru czasu pomiędzy dwoma punktami dość łatwo. Następnie wykonuje konwersję, aby zwrócić bieżący czas w milisekundach.

Edytuj: zaktualizowano na @ sugestie ChrisStratton.

+0

To byłaby bardziej kompletna odpowiedź, gdybyś pokazał konwersję ze struktury do pojedynczej milisekundy lub mikrosekund wartości w typie 64-bitowym ... –

+0

@ ChrisStratton dobra sugestia; edytowane. – mah

+1

Mam mały problem z typami dodać L do liczb np. struct timeval stCurrentTime; gettimeofday (& stCurrentTime, nullptr); return ((long long) stCurrentTime.tv_sec * 1000L) + ((long long) stCurrentTime.tv_usec/1000L); // milseconds –

12

Najlepiej nie używać gettimeofday() lub currentTimeMillis() na urządzeniu mobilnym. Zwracają one czas "zegara ściennego", który może nagle przejść do przodu lub do tyłu, jeśli sieć zaktualizuje czas.

Użyj zegara monotonicznego do pomiarów wydajności - System.nanoTime() lub clock_gettime() z CLOCK_MONOTONIC. Zauważ, że to zwraca raczej struct timespec niż struct timeval; Podstawową różnicą jest to, że rozdzielczość zegara wynosi nanosekundy, a nie mikrosekundy.

int64_t getTimeNsec() { 
    struct timespec now; 
    clock_gettime(CLOCK_MONOTONIC, &now); 
    return (int64_t) now.tv_sec*1000000000LL + now.tv_nsec; 
} 

Oprócz czasu na ścianie możesz być zainteresowany czasem procesora na wątek; patrz Thread Performance in Android.

+0

Jak często aktualizowany jest czas zegara ściennego? Otrzymuję bardzo różne wartości czasu między metodami gettimeofday() i clock_gettime (CLOCK_PROCESS_CPUTIME_ID). Drugi wydaje się bardziej stabilny, ale jego wynikiem jest dłuższy czas niż pierwszy, zamiast tego spodziewałem się mniejszego czasu! –

+1

Można sprawdzić, jak często zegar zegara ściennego jest aktualizowany, nazywając go tak szybko, jak to tylko możliwe w pętli i odejmując wyniki przy pierwszej zmianie wartości. To zależy od urządzenia i wydania do wydania. Zegar PROCESS_CPUTIME przyspiesza tylko wtedy, gdy twój proces działa; jeśli śpi, zegar się nie zmienia. (Zalecam CLOCK_THREAD_CPUTIME_ID dla pracy wydajnościowej, ponieważ postępuje tylko wtedy, gdy bieżący wątek wykorzystuje procesor.) Zegary nie są ze sobą powiązane i nie mogą zaczynać się od zera. – fadden

+0

Mam na myśli to, że mierząc z clock_gettime (CLOCK_PROCESS_CPUTIME_ID) (lub THREAD, same wyniki) na małym zestawie operacji (kilka milisekund) otrzymuję czas równy gettimeofday() lub prosty zegar(). Zamiast tego, w długich cyklach otrzymuję dłuższy czas z pierwszym i tym samym, krótszym czasem z gettimeofday() i zegarem(). UWAGA: we wszystkich przypadkach mierzę czas między punktem końcowym a punktem początkowym, wynik clock_gettime() jest korygowany, jeśli różnica nanosekund <0 (sekundy ++). clock() jest tłumaczone, dzieląc według CLOCKS_PER_SEC. –