Tcl Source Code

View Ticket
Login
Ticket UUID: effa2e2346f8372ad4982d16bad189fab96ceb56
Title: RFE - lazy loading of TclOO for faster interp creation
Type: Bug Version:
Submitter: apnadkarni Created on: 2025-08-16 05:36:29
Subsystem: - New Builtin Commands Assigned To: nobody
Priority: 5 Medium Severity: Minor
Status: Open Last Modified: 2025-08-16 14:30:26
Resolution: None Closed By: nobody
    Closed on:
Description:

Tcl interp creation time more than doubled in 9.{0,1,2} compared to 8.6 as reported in 62019f8aa9. This difference has mostly been negated for 9.0.3 with zipfs related fixes. However, opportunities for further optimization remain. One of these is loading of TclOO. As measured on my system, TclOO initialization takes up close to 40% of interp creation time.

Since a very substantial (majority even?) number of Tcl applications do not use oo, one possibility is to lazy load TclOO. The apn-oo-lazy-init branch implements a proof of concept for this.

For comparison:

Current main branch:

%  timerate {interp delete [interp create]}
1861.39 µs/# 537 # 537.23 #/sec 999.566 net-ms

apn-oo-lazy-init branch:

% timerate {interp delete [interp create]}
1175.20 µs/# 850 # 850.92 #/sec 998.919 net-ms

Test suite passes.

The implementation creates stubs commands for the public oo commands that do initialization on first call. The initialization in turn overwrites the stub implementations with the "real" oo implementation.

Other implementation strategies may be possible (tclIndex, unknown etc.) but need to keep in mind all code paths need to be covered (e.g. initial invocation through namespace path, use of info class commands before any public oo commands etc.

Comments on the proposal, improvements, breakage or even alternative methods appreciated.

User Comments: sebres added on 2025-08-16 14:30:26:

You're welcome.

[6a997a7f19eaa6fa] provides several improvements:

  • package require tcl::oo forces the initialization through new oo::_init command (so one could circumvent the delayed init issues for mockup, injection etc);
  • update of mocked-up command by execution (although it wouldn't "fix" every case sane, see below);
  • code review, dedeplication, etc.

As for mz previous mocked-up example, it'd work now, and would not enter endless loop anymore, but the mock-up becomes outdated (replaced by mentioned update after lazy load), see the new diff (red is lazy branch):

  % rename ::oo::class ::oo::_mocked_class;
  % proc ::oo::class args { puts "mockup $args"; tailcall ::oo::_mocked_class {*}$args }
  % ::oo::class create A
  mockup create A
  ::A
  % ::oo::class create B
- mockup create B
  ::B

So as one can see, the mock-up is quasi removed here. And the only solution would be to use package require tcl::oo before mocking-up or injection to force the initialization.

Alternative would to create all this command properly (to point to correct handler).
Or as already said, a new facility able to load NS on demand by first access to it (in any resolver, etc). In my opinion, that would be the only right way.


apnadkarni added on 2025-08-16 13:42:17:
Thanks for taking a look. I will test the C API with Itcl, which triggered my memory that I think TDBC also uses it.

I think it should be possible to protect the infinite recursion with the mockup as well. Will check.

sebres added on 2025-08-16 13:06:20:

Nice thing.

As for objections or rather theoretical breakage, I think the way you did it is one of the best under these circumstances (without having namespace-based lazy-load facility).

For instance one can rewrite `package require tcl::oo` to force initialisation, so could help for some theoretical case it is really needed (for example like below).

And the possible breakage may be theoretic endless loop in TclOOInitModuleObjCmd, if some command gets injected, mocked-up etc, e. g. by something like this (red is lazy branch):

  % rename ::oo::class ::oo::_mocked_class;
  % proc ::oo::class args { puts "mockup $args"; tailcall ::oo::_mocked_class {*}$args }
  % ::oo::class create A
  mockup create A
- too many nested evaluations (infinite loop?)
+ ::A

As for improvements, I'd later provide my attempt.

> Looking for an extension that uses it ...

I think, Itcl would be good candidate (v4.x is based on tclOO).


apnadkarni added on 2025-08-16 10:39:19:
Note: the branch has not been tested with TclOO's C API. Looking for an extension that uses it ...