[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