|
2026-05-27
| ||
| 10:39 | • Closed ticket [7da6c2d04c]: fileevent poor performance due to shimmering plu... artifact: 9afc3d4e11 user: jan.nijtmans | |
| 10:35 | Fix [7da6c2d04c]: fileevent poor performance due to shimmering check-in: ab9c069c58 user: jan.nijtmans tags: core-9-0-branch | |
| 10:21 | • Ticket [7da6c2d04c] fileevent poor performance due to shimmering status stil... artifact: b6f30ca7fd user: oehhar | |
| 10:17 | • Ticket [7da6c2d04c]: 4 changes artifact: 544a013fa0 user: oehhar | |
| 08:53 | • Ticket [7da6c2d04c]: 3 changes artifact: 4dd45e54f7 user: apnadkarni | |
| 08:43 | • Ticket [7da6c2d04c]: 3 changes artifact: d9a31f4839 user: ralfixx | |
| 00:45 | • Ticket [7da6c2d04c]: 3 changes artifact: d8dcf0ac49 user: emiliano | |
|
2026-05-26
| ||
| 21:53 | Fix [7da6c2d04c]: fileevent poor performance due to shimmering. Same pattern in a lot of other place... check-in: c26a56dd82 user: jan.nijtmans tags: trunk, main | |
| 20:09 | • Ticket [7da6c2d04c] fileevent poor performance due to shimmering status stil... artifact: 5210e020a9 user: dgp | |
| 20:05 | • Ticket [7da6c2d04c]: 3 changes artifact: 32f216cf10 user: dgp | |
| 17:57 | • Add attachment diff to ticket [7da6c2d04c] artifact: 1dfd84f438 user: ralfixx | |
| 17:54 | • New ticket [7da6c2d04c] fileevent poor performance due to shimmering. artifact: a064c6601d user: ralfixx | |
| Ticket UUID: | 7da6c2d04c219e8ed4896b9d4e9eb88e586447f2 | ||
| Title: | fileevent poor performance due to shimmering | ||
| Type: | RFE | Created on: | 2026-05-26 17:54:55 |
| Submitter: | ralfixx | Assigned to: | jan.nijtmans |
| Subsystem: | 24. Channel Commands | Severity: | Important |
| Priority: | 5 Medium | Last modified: | 2026-05-27 10:39:48 |
| Status: | Closed | Closed by: | jan.nijtmans |
| Resolution: | Fixed | Closed on: | 2026-05-27 10:39:48 |
| Version: | 9.0.3 | ||
| Description: | ||||
|
When a fileevent is set up to include the data read from the channel, the performance is dramatically reduced due to shimmering from list to string in Tcl_FileEventObjCmd(). Script: set up a pipeline, and on each read in the fileevent, reset the fileevent script to include the new data. I have intentionally limited the read to 65536 bytes at one time in order to show the problem.
proc read_channel {fd data} {
append data [read $fd 65536]
# puts stderr "[string length $data]"
if {[eof $fd]} {
set now [clock milliseconds]
puts stderr "read [string length $data] bytes in [expr {$now-$::start}]ms"
catch {close $fd}
set ::forever 1
return
}
fileevent $fd readable [list read_channel $fd $data]
}
set fd [open "|dd if=/dev/zero bs=65536 count=200" rb]
fconfigure $fd -blocking 0
set start [clock milliseconds]
fileevent $fd readable [list read_channel $fd ""]
vwait forever
Tcl_FileEventObjCmd() is checking whether to remove the fileevent by issuing a TclGetString() on the fileevent script and checking whether the returned string is '\0'
generic/tclIO.c #9285
/*
* If we are supposed to delete a stored script, do so.
*/
if (*(TclGetString(objv[3])) == '\0') {
DeleteScriptRecord(interp, chanPtr, mask);
return TCL_OK;
}
This causes the fileevent script to shimmer into a string each time the filevent is reset. Proposed patch: I think it is safe to assume that fileevent scripts should be valid lists, so we could check the list length instead. If I do so, the perfomance is greatly enhanced (20x). Original tcl9.0.3
With proposed patch applied:
| ||||
| User Comments: | ||||
dgp added on 2026-05-26 20:05:57:
Be very cautious. I do not think all of Tcl's callback mechanisms are consistent, but some if not most of them allow for a callback *script* and not only a callback command or command prefix. When any script is allowed, it is not at all safe to assume a list value. Make changes based on how you see the code to be written, not on assumptions about "the way it must be". (FWIW, given the fantasy to imagine starting Tcl over, limiting all callbacks to command prefixes would have been a better idea.) dgp added on 2026-05-26 20:09:50:
Also worth noting that string rep generation is not what most people mean by "shimmering". Usually the unwanted effects that get disparaged as shimmering have to do with the loss of an internal rep. Generating a string does not (have to) provoke internal rep. loss. The stork can have two legs on the ground. emiliano added on 2026-05-27 00:45:03:
Note that, on trunk, the check uses the new Tcl_IsEmpty() function introduced with TIP#711, which doesn't generate a string representation if the provided object has a list internal representation ralfixx added on 2026-05-27 08:43:37:
Emiliano, that is great news, even better solution than to fix it in just one place. Donal, thanks for the reminder that "there might be dragons" :-)
fileevent $fd readable "some-func $fd {"
fails with
missing close-brace
while executing
"foo file3 {"
)
apnadkarni added on 2026-05-27 08:53:27:
@ralfixx, and thanks for taking the trouble to track this down, I haven't had time to follow up on c.l.t. oehhar added on 2026-05-27 10:17:41:
Maybe TIP 711 "Tcl_IsEmpty()" may be used to avoid shimmering... oehhar added on 2026-05-27 10:21:33:
Sorry, Jan has replaced all the Tcl_GetString() == \0 by Tcl_IsEmpty in commit [c26a56dd82]. Thanks, Harald jan.nijtmans added on 2026-05-27 10:39:48:
What can be done in 9.0 (which doesn't have Tcl_IsEmpty) is [ab9c069c58ac773e|this]. It's harmless, because it only operates when there is no string representation. The disadvantage of using Tcl_ListObjLength() is that it might shimmer a non-list type to a list, that's what we don't want. | ||||
