Object creation, deletion, and memory usage is ~10x worse in Tcl8.6.4/Itcl4.0.3 than in Tcl8.5.18/Itcl3.4.2.
Demo script:
package require Itcl namespace import itcl::* class A {} set i 0 puts [time {A $i; incr i} 10000] set i 0 puts [time {delete object $i; incr i} 10000]
Results:
+-------+------------+------------+-----------+ | Ver | Create | Delete | Memory | +-------+------------+------------+-----------+ | 3.4.2 | 6.0635 µs | 3.4106 µs | 6.724 MB | | 4.0.3 | 50.0183 µs | 40.6675 µs | 86.556 MB | +-------+------------+------------+-----------+ | ratio | 8.2490 | 11.9238 | 12.872 | +-------+------------+------------+-----------+
Ticket http://core.tcl.tk/itcl/tktview?name=04470f9067 improved the speed immensely, but the current inefficiency may still hinder any future projects using Itcl.
Confirmed I see factor of 4 slower operation in Itcl 4.1.1 compared with 3.4.4.
No idea yet whether there's anything reasonable that can be done about it.
Understood. Just pointing out areas of potential slowdown. I'll put in a couple more.
Object creation local to a proc is 3-4X slower in 4.1.1 vs. 3.2 (don' t have 3.4 numbers)
Itcl 3.2
12 microseconds per iteration for 10000 creation of objects in a proc call
Itcl 4.1.1
45.0342 microseconds per iteration for 10000 creation of objects in a proc call
Note: it's only about 36 microseconds if the SimpleClass is an empty class, ala
itcl::class SimpleClass {}
But it's instructive that adding a variable and method to a class increases the runtime by ~30% in 4.1.1, whereas in 3.2, the runtime stayed at 12-13 microseconds.
Side question - in my profiling, the vast majority of the time (between 3.2 and 4.1.1) appears to be in Tcl_Preserve/Tcl_Release, and those appear to be relatively unchanged between Tcl 8.4 and 8.6. Any idea why this might be? Just used more now? Perhaps teh Tcl_MutexLock/Unlock is slower? (I've got a single Tcl interpreter, there might be other threads in the application, but they're not Tcl related....)
~~~~
I see only 3 calls to Tcl_Preserve() left in the Itcl trunk of development. You're really seeing one or more of them account for significant runtime? Please tell more.
~~~~
Ok. It's only in the implementation of Itcl_PreserveData(),
but that still gets significant use.
There's a build option in Itcl, ITCL_PRESERVE_DEBUG that makes it
use its own implementation instead of a call to Tcl_Preserve. It's possible
that will have a different performance impact.
Sorry, no. At base that implementation also calls Tcl_Preserve.
Looks like the next low-hanging fruit in preserve elimination is ItclMemberCode. Give it a proper refcount as we've done with several other structs now.
So... did you want something specific from me? I could update the Itcl code to see which calls are actually being taken - along with a counter. Let me know, I can modify things.
When an ItclMemberCode improvement is done, we'll want you to try it and determine how much it helps you.
Gladly.
In commit 7388d7698118df3 ItclMemberCode uses reference counting instead of Itcl_PreserveData.
That was huge. Thanks. The time spent in Tcl_Preserve/Tcl_Release is much reduced (from a total of >20 seconds to about 6 seconds). There are no obvious Itcl-related performance issues for this particular usage of my tool. On to the next issue for me!
Can I request a new release of Itcl with this patch on it? 4.1.2? We're trying to finish our porting to Tcl 8.6, and this would help us improve our performance tests to come close to 8.4 performance.
Related performance issue, using latest Itcl (4.1.1) versus 3.2, a 2.6X slowdown in simple script
Itcl 3.2: 4.7 seconds
Itcl 4.1.1: 12.2 seconds
Script is:
Output was literally:
Itcl version: 3.2
4737853 microseconds per iteration
Itcl version: 4.1.1
12256823 microseconds per iteration