There seems to be many extensions/plugins that load all their files when SU starts up.
This is crazy. I’m sure there are many extensions (including native SU extensions) that users aren’t running every time they use SU.
Many extensions could load most of their files on an ‘as needed’ basis, as they aren’t needed until the user interacts with a menu, toolbar, or context menu.
Thoughts? Obviously there is a trade-off, as ‘loading on demand’ will slow up the session ‘first use’ of a plugin, but SU boot time may improve and it will lower the resources Ruby consumes.
Note that require
statements can be guarded with defined?
or const_defined?
, which saves a search of $LOADED_FEATURES
…
Right … Lazy loading. We’ve discussed this here in the past.
Currently this is the responsibility of each extension developer.
(1) Are you perhaps brainstorming some automated way that newbs could easily understand ?
(2) I thought there was a way in Ruby to load modules “on access” … is there still and can it be used within an embedded environment like SketchUp ?
Yes, because sketchup.rb
loads langhadler.rb
, I’ve often suggested …
require 'sketchup' unless defined?(LanguageHandler)
require 'extensions' unless defined?(SketchupExtension)
… for all the extension registrar files in the “Plugins” folder.
This should cut way down on searches through the $LOADED_FEATURES
array during the startup cycle.
EDIT: These require
statements are actually not needed at runtime as SketchUp has alreeady loaded them before it even begins loading any extensions. They might be needed in an IDE if API stubs must be loaded.
I guess that I am referring to Kernel#autoload()
.
The drawback is that it uses Kernel#require
which would not work for .rbe
encrypted files.
So, either the API would need to implement a Sketchup::autoload()
equivalent that can use Sketchup::require
or override the global Kernel#autoload()
to redirect .rbe
files to load with Sketchup::require
.
If the Extension Warehouse enforced a maximum limit, there wouldn’t be an issue.
Right … Lazy loading. We’ve discussed this here in the past.
Yes, I know I’ve brought it up. A common concept in coding is “Don’t waste resources”, and if people have several extensions installed, they could be loading hundreds of files on startup.
As to autoload
, it would be very nice if it worked, and it might, but I’ve never tried.
Also, I’ve asked for a Sketchup.require_relative
, which would also help. One can pass a full path to Sketchup.require
, but that just clutters the code. require_relative
is used in a lot of Ruby code, as it bypasses the RubyGems code.
It’s crazy to boot SU and find hundreds of files in $LOADED_FEATURES
.
JFYI, when using code involving threads, loading files in any way can get messy. It may be fixed in recent Ruby versions, not sure.
The following pattern seems to work:
Lazy Load a Command
# File: "main.rb"
# The main file loaded for an extension.
module SomeAuthor
module SomeNiftyExtension
extend self
# Lazy loader.
def lazy_load(files)
files.each do |file|
Sketchup.require( File.join(__dir__, file) )
end
end
# Initially a method that only loads the files that support it.
def nifty_command
# One of these files will redefine THIS method:
lazy_load(['nifty_support', 'nifty_command'])
# Call the newly redefined edition of this method:
nifty_command()
end
if !defined?(@gui_loaded)
cmd = UI::Command.new('Nifty Command') { nifty_command() }
cmd.tooltip= cmd.status_bar_text= cmd.menu_text
menu = UI.menu('Plugins').add_item(cmd)
@gui_loaded = true
end
end
end
# File: "nifty_command.rb"
# Redefines method nifty_command().
module SomeAuthor
module SomeNiftyExtension
def nifty_command
# Actual command code:
nifty_message()
end
end
end
# File: "nifty_support.rb"
# Supports method nifty_command().
module SomeAuthor
module SomeNiftyExtension
def nifty_message
UI.messagebox("Nifty Command has been loaded.")
end
end
end
Here is a test extension archive:
ADD: Well lazy loading is likely to increase the number of entries in $"
, but after the startup cycle.
I have one extension that’s been in ‘public’ use for at least a dozen years. I don’t remember much of the code in it, and much of it is still rather odd Ruby code, as I was mostly coding with C# and JS when I wrote it. I’ve updated it two or three times, one was a change from WebDialog to HtmlDialog.
Anyway, using const_missing
and a hash of object names/file names, I implemented an autoload
equivalent for the main classes in the extension.
So, it’s possible to centralize file loading and also ‘lazy loading’.
1 Like
Not sure what you mean. If lazy loading was used, the upper limit of $LOADED_FEATURES
’s length would equal what we’re seeing now without lazy loading.
For many users, it might be considerably less, since they probably don’t use all the functionality of every extension they have loaded in every SU session.