Skip to content

Instantly share code, notes, and snippets.

@zoka
Created March 23, 2010 07:28
Show Gist options
  • Save zoka/340921 to your computer and use it in GitHub Desktop.
Save zoka/340921 to your computer and use it in GitHub Desktop.
#include <node.h>
#include <sys/time.h>
using namespace v8;
using namespace node;
Handle<Value>
seconds(const Arguments& args)
{
timeval t1;
HandleScope scope;
gettimeofday(&t1, NULL);
return Number::New((double)t1.tv_sec + (double) t1.tv_usec / 1000000.0);
}
extern "C" void
init (Handle<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> _seconds = FunctionTemplate::New(seconds);
target->Set(String::New("seconds") , _seconds->GetFunction());
}
##include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
// compile: g++ -o ttest ttest.cc
long long llong_time(timeval& t) {
return (long long)t.tv_sec * 1000000 + (long long) t.tv_usec;
}
long ulong_time(timeval& t) {
return (unsigned long )(t.tv_sec * 1000000 + t.tv_usec);
}
double double_time(timeval& t) {
return (double)t.tv_sec + (double) t.tv_usec / 1000000.0;
}
int main (void) {
unsigned long ul_now, ul_before;
long long ll_now, ll_before;
double d_now, d_before;
timeval now, before;
printf("Sleeping for one second ...\n");
gettimeofday(&before, NULL);
usleep(1000000);
gettimeofday(&now, NULL);
printf("Sizeof unsigned long is %d\n", sizeof(unsigned long));
printf("Sizeof long long is %d\n", sizeof(long long));
printf("As unsigned long: before=%lu usec now=%lu usec ",
ul_before = ulong_time(before),
ul_now = ulong_time(now));
printf("delta=%ld usec\n", ul_now - ul_before);
printf("As long long: before=%lld usec now=%lld usec ",
ll_before = llong_time(before),
ll_now = llong_time(now));
printf("delta=%lld usec\n", ll_now - ll_before);
printf("As double: before=%f sec now=%f sec ",
d_before = double_time(before),
d_now = double_time(now));
printf("delta=%f sec\n", d_now - d_before);
int i;
gettimeofday(&before, NULL);
ul_before = ulong_time(now);
for (i = 0; i < 1000000; i++);
ul_now = ulong_time(before);
gettimeofday(&now, NULL);
ul_now = ulong_time(now);
printf("ulong_time() overhead for 1000000 invocations =%ld usec\n", (ul_now - ul_before));
gettimeofday(&before, NULL);
d_before = double_time(before);
for (i = 0; i < 1000000; i++);
d_now = double_time(now);
gettimeofday(&now, NULL);
d_now = double_time(now);
printf("double_time() overhead for 1000000 invocations=%f sec\n", (d_now - d_before));
}
Here is output of above program on OS X:
$ ./ttest
Sleeping for one second ...
Sizeof unsigned long is 4
Sizeof long long is 8
As unsigned long: before=2061213856 usec now=2062213848 usec delta=999992 usec
As long long: before=1269328105939104 usec now=1269328106939096 usec delta=999992 usec
As double: before=1269328105.939104 sec now=1269328106.939096 sec delta=0.999992 sec
ulong_time() overhead for 1000000 invocations =2540 usec
double_time() overhead for 1000000 invocations=0.002471 sec
Conclusion:
Using unsigned long leads to multiplication overflow,
although the delta still seems to be correct for short intervals (less than ~ 4000 seconds).
Moreover, it is a just luck that C runtime multiplication overflow seems to preserve the difference.
This may not work on another platform.
Using llong_time() in Node is not possible since 64-bit integers are not supported as
JavaScript type.
Note that double_time() is slightly faster than ulong_time() which is quite amazing.
So, I think that just one floating point method that provides value in seconds should
be sufficient.
See bindings.cc above, note that original seconds() method had improper casting order,
which would lead to loss of precision.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment