CompusaMedlem sedan jan. 20022 952 inlägg
Finns det något smidigt sätt i C att få fram en timestamp i millisekunder? Jag är egentligen endast intresserad av endast millisekunder, datum osv skiter jag i ;)
Har sökt och letat lite här och var, bland annat på google, men de flesta lösningarna verkar gälla C++ och det har jag inte möjlighet att använda.
Hittade ett exempel här, men det sträcker sig bara till sekunder vilket är alldeles för stort för mig...
#include <stdio.h>
#include <time.h>
void timestamp(FILE *out)
{
struct tm *tmp;
time_t t;
t = time(NULL);
tmp = localtime(&t); /* or gmtime, if you want GMT^H^H^HUTC */
fprintf(out, "%02d.%02d.%04d %02d:%02d:%02d",
tmp->tm_mday, tmp->tm_mon+1, tmp->tm_year+1900,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
}
/* example of how to call this function: */
int main()
{
printf("The current date and time are: ");
timestamp(stdout);
printf("\n");
return 0;
}
syntax high
CompusaMedlem sedan jan. 20022 952 inlägg
Nu har jag fått det här att fungera på följande vis:
#include <stdio.h>
#include <sys/timeb.h>
int main()
{
struct timeb tm;
ftime(&tm);
printf("Digit: %d \n", tm.millitm);
int i = 0;
while(i < 1000000) {
i++; // fake progress
}
ftime(&tm);
printf("Digit: %d \n", tm.millitm);
}
Är fortfarande inte säker på om detta är vad jag vill ha... ska undersöka saken.
LaspMedlem sedan juli 200010 197 inlägg
Jag tror inte att du kan få rätvisande millisekunder i Windows som operativ.
Då måste du köra RTOS av något slag.
nitro2k01Medlem sedan aug. 20037 630 inlägg
Lasp skrev:
Jag tror inte att du kan få rätvisande millisekunder i Windows som operativ.
Då måste du köra RTOS av något slag.
Att mäta millisekunder på detta vis är inget problem, eftersom denna data plockas från ett separat dedikerat timer-chip. Det du antagligen tänker på är att man behöver ett RTOS för att en server med större sannolikhet ska svara inom millisekunder.
CompusaMedlem sedan jan. 20022 952 inlägg
Får segmentation fault när jag försöker subtrahera av en timestamp från en annan. Någon som har en aning om hur jag ska göra detta?
#include <stdio.h>
#include <sys/timeb.h>
int main()
{
struct timeb tm;
ftime(&tm);
//tm.millitm will then contain the millisec part.
printf("Hello World! \n");
unsigned short tm1 = tm.millitm;
printf("Digit: %d \n", tm1);
int i = 0;
while(i < 1000000) {
i++; // fake progress
}
ftime(&tm);
unsigned short tm2 = tm.millitm;
printf("Digit: %d \n", tm2);
unsigned short tot = tm2 - tm1;
printf("Det tog %d millisekunder %n", tot); // ORSAKAR FELET
}
Peter SMedlem sedan dec. 20025 484 inlägg
CompusaMedlem sedan jan. 20022 952 inlägg
Tack Peter S. Nog ett av de mest pinsamma felen jag stirrat mig blind på. Helt sjukt. Nästan så att du var värd rätt svar :e
Nåväl här är en fungerande lösning som jag tror gör vad den ska, kanske någon som kan ha användning för den nån gång, who knows..
#include <stdio.h>
#include <sys/timeb.h>
int main()
{
struct timeb tm;
ftime(&tm);
unsigned short timestamp1 = tm.millitm;
printf("Digit: %d \n", timestamp1);
int i = 0;
while (i < 1000000) {
i++; // fake progress
}
ftime(&tm);
unsigned short timestamp2 = tm.millitm;
printf("Digit: %d \n", timestamp2);
unsigned short total;
if (timestamp1 < timestamp2) {
total = timestamp2 - timestamp1;
}
else
{
total = 1000 - (timestamp1 - timestamp2);
}
printf("Det tog %d millisekunder \n", total);
}
Sang-draxMedlem sedan juli 2002570 inlägg
Lasp skrev:
Jag tror inte att du kan få rätvisande millisekunder i Windows som operativ.
Vanliga API-funktioner (såsom GetTickCount() etc.) har om jag minns rätt inte riktigt upplösning ner till millisekunder, men du kan alltid använda QueryPerformanceCounter() eller assemblerinstruktionen rdtsc så erhålls upplösning i storleksordning av processorns klockfrekvens (nanosekunder).
Sang-draxMedlem sedan juli 2002570 inlägg
Så här kan du mäta antalet klockcykler sedan datorn startades:
inline __int64 rdtsc64()
{
unsigned long int lowPart;
unsigned long int highPart;
__asm
{
pushad
cpuid
rdtsc
mov highPart, edx
mov lowPart, eax
popad
}
__int64 value;
value = ((__int64)highPart << 32) | lowPart;
return value;
}
Har du inte __int64 och måste nöja dig med 32 bitar ser det ut så här (och då kan du heller inte mäta tider längre än ett par sekunder):
inline unsigned long int rdtsc32()
{
unsigned long int lowPart;
__asm
{
pushad
cpuid
rdtsc
mov lowPart, eax
popad
}
return lowPart;
}
EDIT:
Om inte din kompliator fattar instruktionerna rtdsc och cpuid så lägg till dessa rader:
#define cpuid __asm __emit 0fh __asm __emit 0a2h
#define rdtsc __asm __emit 0fh __asm __emit 031h
CompusaMedlem sedan jan. 20022 952 inlägg
Coolt! Ska kika på detta :)
Sangdrax, hur verkar min lösning i övrigt? Är den nått sånt där tillförlitlig när det gäller timestamps i millisekunder? Ansi C (ren C) är det jag kompilerar för.
Sang-draxMedlem sedan juli 2002570 inlägg
Här står det att GetTickCount() har en noggrannhet på 10-55 ms:
http://en.wikibooks.org/wiki/Programming:C_-/-_-/-_Win32#Time
Nu är det ju inte den funktionen du använder, utan du använder dig av datorns klocka. Dock tar ditt anrop till ftime() troligtvis avsevärt längre tid än GetTickCount, så vem vet? rdtsc är både jättesnabb att anropa och mycket exakt.
Bättre svar oavsett metod får du om du gör samma test massor av gånger och bildar medelvärdet.
CompusaMedlem sedan jan. 20022 952 inlägg
Sang-drax skrev:
inline unsigned long int rdtsc32()
{
unsigned long int lowPart;
__asm
{
pushad
cpuid
rdtsc
mov lowPart, eax
popad
}
return lowPart;
}
Sang-drax, förstår inte hur jag ska få koden ovan att göra något liknande det jag gör i min urpsrungliga lösningen. Fungerar verkligen den kod i ren C (ej C++ eller liknande)? Om du vet hur denna skulle se ut så får du gärna visat.
Har mätt lite med min funktion på samma tasks och jag har fått diffar på ungefär 11 millisekunder, men det kan ju bero på att CPU:n belastas olika när jag gör testerna.
Sang-draxMedlem sedan juli 2002570 inlägg
1. Kompilerar koden? Om inte, vilka fel får du?
2. Gör så här för att mäta antal instruktioner som en viss uppgift tar:
unsigned long start = Rdtsc32();
//Gör något
unsigned long timeTaken = Rdtsc32() - start;
printf("Uppgiften tog %u instruktioner.",timeTaken);
CompusaMedlem sedan jan. 20022 952 inlägg
Vet inte om jag missförstår dig men hur ska jag få millisekunder av det här??
Alternativ sekunder i float 0,001 osv.
CompusaMedlem sedan jan. 20022 952 inlägg
Ah, jag googlade lite och det ska tydligen gå att kovertera från klock cykler (samma som instruktioner) till millisekunder på följande vis:
http://www.javaworld.com/javaworld/jw-10-1998/jw-10-letters.html
Milliseconds = (clock cycles / 1,000) / ( speed of your CPU in MHz)
So, for example, a 300 clock cycle operation on a 300 MHz machine takes: (300 clock cycles / 1,000)/(300 MHz) = 0.001 milliseconds.
Testat denna kod
#define cpuid __asm __emit 0fh __asm __emit 0a2h
#define rdtsc __asm __emit 0fh __asm __emit 031h
inline unsigned long int rdtsc32()
{
unsigned long int lowPart;
__asm
{
pushad
cpuid
rdtsc
mov lowPart, eax
popad
}
return lowPart;
}
int main()
{
// Will add code here when I can compile
return 0;
}
Får följande fel när jag kompilerar med gcc i cygwin:
Sang-draxMedlem sedan juli 2002570 inlägg
Funkar det inte utan #define-raderna? En mycket bra gratis kompilator som klarar denna kod är Micosoft Visual C++ 2005 Express.
<EDIT>
Det verkar som kompilatorn har problem med "__asm". Fungerar "asm" i stället?
</EDIT>
Om din processor är 1.5GHz så får du tiden i sekunder så här:
double seconds = double(timeTaken) / 1.5e9;
CompusaMedlem sedan jan. 20022 952 inlägg
C++ eller Visual C++ kan jag inte använda. Har tillåtelse att använda tillgång ansi C och gcc-kompilatorn under cygwin.
niklas_sMedlem sedan juli 20055 inlägg
Detta fungerar i GCC:
#include <stdio.h>
#include <time.h>
extern __inline__ unsigned long long int rdtsc() {
unsigned long long int x;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
return x;
}
int main(void) {
unsigned long long t1, t2;
t1 = rdtsc(); // Hämta clk från CPU.
sleep(10); // Vänta 10 sekunder.
t2 = rdtsc(); // Hämta clk från CPU.
printf("=== Klockfrekvens: %G MHz ===\n", (double)((t2-t1)/1000)/10000);
}
Sang-draxMedlem sedan juli 2002570 inlägg
Niklas, ett tips är att köra cpuid innan rdtsc så att processorn tömmer sin "kö" och verkligen kör instruktionerna som kommer efter rdtsc efter och inte före.
CompusaMedlem sedan jan. 20022 952 inlägg
Kanonbra, tack för svaret Niklas och hjälpen Sang-drax. Har en annan lösning som ska vara väldigt bra men som jag ej ännu hunnit sätta mig in i. Blir eventuellt ikväll, återkommer om detta.
Den lösningen som jag postade i inlägg nummer #5 visade sig inte vara bra när jag använde den i praktiken, dvs det system som den är ämnad för. Min uträkningar visade ibland rätt resultat och ibland fel, vilket visade sig vara på grund av den icke-tillförlitliga "ftime".