Renoise tools - speed optimization initiative

Apparently, this only happens with renoise.song().

Yes, because all the other objects are always present. But a song might not always be present - especially, during startup.

It used to be, but (if memory serves me right) tool initialization was pushed to an earlier point in the startup process to ensure that a “meta tool” such as the tool updater was able to intercept and do it’s thing.

In any case, while joule’s example is certainly compact in it’s syntax, it doesn’t entirely solve the problem. I mentioned “auto-launching” tools - that is, tools that are “doing stuff” on startup, without any user interaction (a common example: registering observables). Such a tool absolutely depends on the presence of a song object - and joule’s code doesn’t guarantee that the renoise.song() actually exists - only that it’s kept up to date.

So the workaround is still: for code that executes on it’s own (auto-launching), ensure that this is only performed_after_app_new_document_observable has fired.

For every part of a tool which is invoked as a consequence of a user action, there is no such problem or complexity to take care of.

Yes, because all the other objects are always present. But a song might not always be present - especially, during startup.

There was an earlier time when it was, but (if memory serves me right) tool initialization was pushed to an earlier point in the startup process to ensure that a “meta tool” such as the tool updater was able to intercept and do it’s thing.

In any case, while joule’s example is certainly compact in it’s syntax, it doesn’t entirely solve the problem. I mentioned “auto-launching” tools - that is, tools that are “doing stuff” on startup, without any user interaction (a common example: registering observables). Such a tool absolutely depends on the presence of a song object - and joule’s code doesn’t guarantee that the renoise.song() actually exists - only that it’s kept up to date.

So the workaround is still: for code that executes on it’s own (auto-launching), ensure that this is only performed_after_app_new_document_observable has fired.

For every part of a tool which is invoked as a consequence of a user action, there is no such problem or complexity to take care of.

In the Joule indications it is described that the code is necessary to place it just above the main.lua. This code would be the first thing you would read to refer to renoise.song().Afterwards, it is necessary to always use the global “song”. Does not this avoid any errors, even with “auto-launching” tools?

I’m not sure, but I think this eliminates any error scenario caused by “song”. Another thing is the need to add new_document_observable for certain things that the tool needs to update, in case of loading a new song, when starting Renoise, or changing the song. For example, I have needed to include a new_document_observable to update the status of the “edit mode” button of my tool (change the color of a button). But if it is not included, the tool simply does not update it, but it does not return the dreaded error.

I’m still confused with this topic. If you create a function that needs access to renoise.song(), and then execute it, the tool will require, at least once, that renoise.song () exist.This would not be like a tool of type “auto-launching”?In this case, the code described by Joule, provided that the function is defined and executed later.

So, I ask myself: what is the need for a tool to be executed before renoise.song () is available?Would not it have the same effect if it were loaded later?Correct me if I’m wrong: There is only one possible scenario where there is no renoise.song (), and it is just when renoise is executed, that the song has not yet been created.

Something that heavily speeds up “classes” is to use closure based function classes instead of the standard ones that are using metatables. In many cases, these stupid classes are enough.

I get about four times the performance on simple lookups with this pattern, compared to normal classes (class “keyword” or traditional lua classes). It´s stupid and simple but an effective way to avoid overhead while still providing convenient “objects” and syntax. It´s also possible to mimic inheritance if needed.

Basically, you get “OOP” with clean tables without metatable/metamethod bloat.

Summary

function fastDog(args)

  -- object variables
  local self = { events = {}, value = 1 }

  -- add your class methods. obj parameter = colon sugar.
  self.add_child = function(obj, child)
    self.events[#self.events+1] = obj
  end
  
  self.render = function(obj)
    return obj.value
  end

  -- ":__init" stuff goes here. just an example.
  for _, child in ipairs(args) do
    self:add_child(child)
  end
  
  return self
  -- or return a custom table to only expose properties/methods meant to be public.
end