Tcl Source Code

Check-in [6593536677]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:unix: monotonic time (performance counter/wide-clicks) - implements several fallbacks for platforms without monotonic time (older Darwin, MacOSX or xcode)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sebres-8-5-event-perf-branch
Files: files | file ages | folders
SHA3-256: 6593536677b62f7d12e157a8727c3e6510b131765d9c363a200a2ad2c086760a
User & Date: sebres 2019-03-08 15:38:05
Context
2019-03-09
18:41
TclpScaleUTime fixed typo, only if native scaling used (tclScaleTimeProcPtr == NativeScaleTime) the ... check-in: fca5fb3444 user: sebres tags: sebres-8-5-event-perf-branch
2019-03-08
15:39
merge 8-5-event-perf-branch (no monotonic time fallbacks) check-in: ec9b47d045 user: sebres tags: sebres-8-6-event-perf-branch
15:38
unix: monotonic time (performance counter/wide-clicks) - implements several fallbacks for platforms ... check-in: 6593536677 user: sebres tags: sebres-8-5-event-perf-branch
04:38
merge 8.5 (fixed performance test for short exec-time) check-in: 177092d5da user: sebres tags: sebres-8-5-event-perf-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to unix/tclUnixTime.c.

135
136
137
138
139
140
141



142
143
144
145



146
147












148
149
























150
151
152
153
154
155
156
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217



218
219
220
221
222
223
224
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270



271
272
273
274
275
276
277
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetUTimeMonotonic(void)
{



    struct timespec mntv;
    if ( tclGetTimeProcPtr == NativeGetTime
      && clock_gettime(CLOCK_MONOTONIC, &mntv) == 0
    ) {



	/* monotonic time since some starting point in microseconds */
	return ((Tcl_WideInt)mntv.tv_sec)*1000000 + mntv.tv_nsec / 1000;












    } else {
    	/* fallback via tclGetTimeProcPtr */
























	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	return ((Tcl_WideInt)time.sec)*1000000 + time.usec;
    }
}
 
................................................................................

Tcl_WideInt
TclpGetWideClicks(void)
{
    Tcl_WideInt now;

    if (tclGetTimeProcPtr == NativeGetTime) {
#ifndef MAC_OSX_TCL
    	/* 1 wide click == 0.001 microseconds (1 nanosecond) */
	struct timespec mntv;
	
	(void)clock_gettime(CLOCK_MONOTONIC, &mntv);
	return ((Tcl_WideInt)mntv.tv_sec)*1000000*1000 + mntv.tv_nsec;
#else	/* MAC_OSX_TCL: */
	/* 1 wide click == (tb.numer / tb.denom / 1000) microseconds */
	return (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);



#endif
    } else {
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	Tcl_Time time;

	(*tclGetTimeProcPtr) (&time, tclTimeClientData);
	now = ((Tcl_WideInt)time.sec)*1000000 + time.usec;
................................................................................
double
TclpWideClicksToNanoseconds(
    Tcl_WideInt clicks)
{
    double nsec;

    if (tclGetTimeProcPtr == NativeGetTime) {
#ifndef MAC_OSX_TCL
	/* 1 wide click == 0.001 microseconds (1 nanosecond) */
	return clicks;
#else	/* MAC_OSX_TCL: */
	/* 1 wide click == (tb.numer / tb.denom) nanoseconds */
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;
	
	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
	} else {
	    nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
	}



#endif
    } else {
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	nsec = clicks * 1000;
    }

    return nsec;






>
>
>
|
<
|
<
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|




|


>
>
>







 







|


|













>
>
>







135
136
137
138
139
140
141
142
143
144
145

146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetUTimeMonotonic(void)
{
    if (tclGetTimeProcPtr == NativeGetTime) {
#if defined(CLOCK_MONOTONIC)
	/* monotonic time available on this platform */
	struct timespec mntv;

	if (clock_gettime(CLOCK_MONOTONIC, &mntv) != 0) {

	    /* fallback to non-monotonic real-time. */
	    return TclpGetMicroseconds();
	}
	/* monotonic time since some starting point in microseconds */
	return ((Tcl_WideInt)mntv.tv_sec)*1000000 + mntv.tv_nsec / 1000;
#elif defined(MAC_OSX_TCL)
	/* absolute time related (tb.numer / tb.denom / 1000) microseconds */
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;
	uint64_t clicks = mach_absolute_time();

	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    return (Tcl_WideInt)(((uint64_t) clicks) * tb.numer / 1000 / tb.denom);
	} else {

	    return (Tcl_WideInt)(((uint64_t) clicks) / 1000 * tb.numer / tb.denom);
	}

#else	/* no MAC_OSX_TCL and no monotonic time (xcode etc) */

    /* fallback to non-monotonic real-time (microseconds) */
    return TclpGetMicroseconds();
    /*
     * TODO: may be the seconds could be obtained over the uptime (since last boot),
     * like here (https://stackoverflow.com/questions/20817311/ios-real-monotonic-clock-other-than-mach-absolute-time):
	    int mib[2] = {CTL_KERN, KERN_BOOTTIME};
	    size_t size = sizeof(boottime);
	    time_t now;
	    time_t uptime = -1;
	    (void)time(&now);
	    if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
	    {
		uptime = now - (boottime.tv_sec);
	    }
     * but I don't think this could provide even micro- or milliseconds granularity,
     * so a not back-drifting (monotonic) mix-in would be necessary.
     */
#endif
    } else {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	return ((Tcl_WideInt)time.sec)*1000000 + time.usec;
    }
}
 
................................................................................

Tcl_WideInt
TclpGetWideClicks(void)
{
    Tcl_WideInt now;

    if (tclGetTimeProcPtr == NativeGetTime) {
#if defined(CLOCK_MONOTONIC)
	/* 1 wide click == 0.001 microseconds (1 nanosecond) */
	struct timespec mntv;
	
	(void)clock_gettime(CLOCK_MONOTONIC, &mntv);
	return ((Tcl_WideInt)mntv.tv_sec)*1000000*1000 + mntv.tv_nsec;
#elif defined(MAC_OSX_TCL)
	/* 1 wide click == (tb.numer / tb.denom / 1000) microseconds */
	return (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);
#else	/* no MAC_OSX_TCL and no monotonic time (xcode etc) */
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	return TclpGetMicroseconds();
#endif
    } else {
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	Tcl_Time time;

	(*tclGetTimeProcPtr) (&time, tclTimeClientData);
	now = ((Tcl_WideInt)time.sec)*1000000 + time.usec;
................................................................................
double
TclpWideClicksToNanoseconds(
    Tcl_WideInt clicks)
{
    double nsec;

    if (tclGetTimeProcPtr == NativeGetTime) {
#if defined(CLOCK_MONOTONIC)
	/* 1 wide click == 0.001 microseconds (1 nanosecond) */
	return clicks;
#elif defined(MAC_OSX_TCL)
	/* 1 wide click == (tb.numer / tb.denom) nanoseconds */
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;
	
	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
	} else {
	    nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
	}
#else	/* no MAC_OSX_TCL and no monotonic time (xcode etc) */
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	return clicks * 1000;
#endif
    } else {
	/* 1 wide click == 1 microsecond (1000 nanoseconds) */
	nsec = clicks * 1000;
    }

    return nsec;