[MLton] Re: [MLton-user] FFI and pointer relocation
Matthew Fluet
fluet at tti-c.org
Wed Nov 28 07:23:43 PST 2007
On Wed, 28 Nov 2007, Wesley W. Terpstra wrote:
> On Nov 27, 2007, at 5:15 AM, Matthew Fluet wrote:
>> I suppose one could use MLton.Pointer functions to fetch the tv_sec and
>> tv_usec fields of the statically allocated struct timeval, though the
>> overhead of making a C call is really the fact that one needs to move ML
>> pointers to the stack, not leaving them in registers. So, while there is
>> some overhead of the subsequent C calls, it probably isn't that much over
>> the initial call, especially since the gettimeofday is a system call. Also,
>> you need to be robust against changes to the suseconds_t representation on
>> different platforms, and the offset in the timeval struct. So, I'm not
>> sure the added complexity is worth it.
>
> The cost of running gettimeofday() is actually dominated by the IntInf
> conversions (not the system call). Once those are eliminated by using Int64,
> you're right that the two extra function calls have almost no cost.
> I was mostly proposing this because I think it's actually *simpler* than the
> additional function calls: My proposal is that gettimeofday() call should
> copy the values from a locally scoped timeval struct into globally scoped
> C_Time_t and C_SUSeconds_t values which can be (type-safely) fetched via
> _symbol:
>
> C_Time_t Time_sec;
> C_SUSeconds_t Time_usec;
> int gettimeofday() {
> struct timeval timeval;
> int res;
> res = gettimeofday (&timeval, (struct timezone*)NULL);
> Time_sec = timeval.tv_sec;
> Time_usec = timeval.tv_usec;
> return res;
> }
Fair enough; that is simpler than fetching through the struct timeval.
Though, on the ML side, _symbol will still yield a "unit -> C_Time.t"
function, so the ML code will look nearly the same.
>> > On the topic of gettimeofday, isn't Time.time as an IntInf instead of an
>> > Int64 a bit costly?
>>
>> Not necessarily. Small IntInf values (< 31 bits or < 63 bits, depending on
>> the platform) are maniputated directly, with just a couple of bit shifts
>> and arithmetic ops. It is only if you need more bits that you need to use
>> the GMP library code, which is itself pretty fast.
>
> Except that all uses of Time.time larger than 1 second will be larger than 30
> bits (signed).
>
>> Also, to preserve nanosecond resolution in time values, you either need to
>> use IntInf or two fixed integer values, and the added complexity of doing
>> the appropriate sec/nanosec pair arithmetic.
>
> I proposed Int64. That's good until the year 2242 at nanosecond accuracy.
Right, but doesn't allow you express times beyond that point.
We used to implement Time.time as
datatype time = T of {sec: Int.int, usec: Int.int}
but switched to using IntInf.int (representing microseconds since the
epoch) in Sep. 2003:
http://mlton.org/pipermail/mlton/2003-September/024318.html
and then shortly thereafter using IntInf.int (representing nanoseconds
since the epoch).
The only discussion I could find on the choice of Time.time representation
were back from July 2001:
http://mlton.org/pipermail/mlton/2001-July/019405.html
>> Time.time manipulations are rare to begin with, and I've never seen them be
>> a dominant factor in a program
>
> In a well written network application, an strace looks like: select()
> gettimeofday() maybe read() maybe write() gettimeofday() repeat.
I'm curious as to why you need so many gettimeofday() calls.
More information about the MLton
mailing list