It is currently May 20th, 2019, 11:32 am

Question on DynamicVariables=1

Help with creating, editing & fixing problems with skins
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Question on DynamicVariables=1

Yincognito » February 3rd, 2019, 4:54 am

This is somewhat a more technical question...the manual says that Rainmeter uses marginally more processor power when DynamicVariables=1 is set on measures or meters, but I'd like to know if this depends strictly on the option being set OR on how many times those dynamic "variables" change while a skin is active.

For example, if I have a skin using DynamicVariables=1 while drawing some shapes and setting some meter styles, but the dynamic variables used in the process change only once (e.g. when the skin is drawn, from 0 to some other value), would that skin use less CPU compared to, say, a similar skin performing multiple changes to those dynamic variables? Or the mere fact that DynamicVariables=1 is set on those skin elements determines the additional CPU usage, irrespective of how many times the variables are being changed while the skin is active? Please consider that despite the variables only changing once, the meters on which the said meter styles are applied to are updating "normally" (i.e. they don't have UpdateDivider=-1 set on them, only the shapes do).

Going a little further, does setting DynamicVariables=1 on the visual elements of a "Stay Topmost" skin impact the performance more, compared to setting the same option on a skin whose position is set to "Normal" on the screen? Considering that the "Stay Topmost" skins are constantly redrawn to keep them on the top of everything else (something that's easily visible when two "Stay Topmost" skins overlap each other), thus the initial 0 to some value variable change is, in theory, performed more often...

NOTE: My questions refer to the additional CPU usage of the actual DynamicVariables=1 being set, not to the complexity of the things done with the help of those dynamic variables, so disregard the latter aspect, if possible.
rxtd
Posts: 94
Joined: April 30th, 2017, 11:51 am

Re: Question on DynamicVariables=1

rxtd » February 3rd, 2019, 5:00 pm

Yincognito wrote:
February 3rd, 2019, 4:54 am
DynamicVariables=1 forces meter/measure to reread all option, regardless of whether there was any changes.
Actually I don't know exactly, because I didn't read code of all meters. Maybe some meters cache something. But I didn't notice anything like it.

If in your skin changes only happen once, consider disabling DynamicVariables and just changing options with !SetOption bang.
If you use formulas, that change at some point (i.g., if you use variables, and you want a meter to update according to changes in variables), you can use bang [!SetOption MeterName SomeNonExistentOptionName]. This will force Rainmeter to reread options on that meter one time.

I don't know if visibility of skin changes anything for Rainmeter.
But updates of meters/measures doesn't have anything to do with redraw, these are two separate actions. And while you can skip redraw if skin is not visible to user, you can't skip update, because update has side-effects (for example, Line meter updated displaying values on update), so "Stay Topmost" shouldn't affect updating.
In theory there may be some caches for redraw process, but... Well, I don't think there are, and if there are, I don't think it matters.
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Re: Question on DynamicVariables=1

Yincognito » February 3rd, 2019, 5:44 pm

rxtd wrote:
February 3rd, 2019, 5:00 pm
DynamicVariables=1 forces meter/measure to reread all option, regardless of whether there was any changes.
Actually I don't know exactly, because I didn't read code of all meters. Maybe some meters cache something. But I didn't notice anything like it.

If in your skin changes only happen once, consider disabling DynamicVariables and just changing options with !SetOption bang.
If you use formulas, that change at some point (i.g., if you use variables, and you want a meter to update according to changes in variables), you can use bang [!SetOption MeterName SomeNonExistentOptionName]. This will force Rainmeter to reread options on that meter one time.

I don't know if visibility of skin changes anything for Rainmeter.
But updates of meters/measures doesn't have anything to do with redraw, these are two separate actions. And while you can skip redraw if skin is not visible to user, you can't skip update, because update has side-effects (for example, Line meter updated displaying values on update), so "Stay Topmost" shouldn't affect updating.
In theory there may be some caches for redraw process, but... Well, I don't think there are, and if there are, I don't think it matters.
Thank you for clarifying some things, rxtd - much appreciated. The reason I asked this is because I tried both ways and overall, for a longer period of time, there isn't much difference (e.g. for 30+ minutes of averaging Rainmeter's CPU usage, I come to roughly 1% CPU used in both cases). Sure, the impact of DynamicVariables=1 is marginal, as per the manual, but in the end it makes very little (if none) difference. I think I'll stick with DynamicVariables=1 for the time being, despite being more CPU intensive in theory, because it makes some formulas much more clear in the code, as opposed to a !SetOption bang on a long line, where everything is getting added, subtracted, multiplied and divided, making identifying calculated things very difficult.

That being said, the manual also says that "You may not use !SetOption to change any setting on a plugin measure that is specific to that kind of plugin if the plugin does not currently support DynamicVariables=1", so I reckon that despite being advertised as an alternative to DynamicVariables=1, !SetOption is also using a form of dynamic variables... :???:

P.S. The whole thing I'm using this on is setting up the dimensions and positions of the meters and the skin with the help of another set of transparent "placeholder" meters that have to fit certain strings written using some randomly picked font/font size. Since there isn't any way of getting the W and H of meters that are using some font/font size before they are actually drawn on the skin, that's about the only trick able to be used to have those dimensions before the actual meters are being displayed.
rxtd
Posts: 94
Joined: April 30th, 2017, 11:51 am

Re: Question on DynamicVariables=1

rxtd » February 3rd, 2019, 7:24 pm

Yincognito wrote:
February 3rd, 2019, 5:44 pm
I tried both ways and overall, for a longer period of time, there isn't much difference (e.g. for 30+ minutes of averaging Rainmeter's CPU usage, I come to roughly 1% CPU used in both cases)
Yeah, it doesn't matter that much. I believe, you need a lot of meters/measures with complex formulas to suffer from dynamic variables. Like, several hundreds, each having a lot of complex formulas in many options.
Yincognito wrote:
February 3rd, 2019, 5:44 pm
I think I'll stick with DynamicVariables=1 for the time being, despite being more CPU intensive in theory, because it makes some formulas much more clear in the code, as opposed to a !SetOption bang on a long line, where everything is getting added, subtracted, multiplied and divided, making identifying calculated things very difficult.
As I said, you can leave this that way and just use empty !SetOption for nonexistent option to force update. Well, if you bother about that little difference in performance.
Yincognito wrote:
February 3rd, 2019, 5:44 pm
I reckon that despite being advertised as an alternative to DynamicVariables=1, !SetOption is also using a form of dynamic variables... :???:
They both force meter/measure to reread all of its options.
Th difference is that with DynamicVariables=1 options are updated every time an element is updated, but with !SetOption it only happens once after bang.
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Re: Question on DynamicVariables=1

Yincognito » February 3rd, 2019, 7:47 pm

rxtd wrote:
February 3rd, 2019, 7:24 pm
Yeah, it doesn't matter that much. I believe, you need a lot of meters/measures with complex formulas to suffer from dynamic variables. Like, several hundreds, each having a lot of complex formulas in many options.
I actually tried making a test skin with 100 measures (not meters this time) using dynamic variables, and compared to the same skin with 200 static measures that accomplished the same thing, and there was no difference whatsoever. In that case I was trying to see whether is more efficient to have an additional measure to accomplish the things achieved using a single dynamic variables enabled measure, but the results can be used as an argument in this case too.

Of course, I had nothing else in that test skin to make it more complex, so that could be another reason why the difference wasn't noticeable. This is the case with my actual (minimalistic) skins too, as I don't use images, animations and other CPU intensive stuff - they are already efficiency oriented from the start.

P.S. The empty !SetOption is a good idea though, and good to know that you can force an additional update when necessary.
User avatar
jsmorley
Developer
Posts: 19245
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Question on DynamicVariables=1

jsmorley » February 3rd, 2019, 8:45 pm

!SetOption doesn't force an extra update, but simply makes the target measure or meter behave as if it had DynamicVariables=1 on it for one, the next, update. So all options (including any you set with !SetOption) are fully evaluated and resolved on the next update.

The behavior is probably easiest to see if you look at code for an empty plugin template.

Code: Select all

#include <Windows.h>
#include "../../API/RainmeterAPI.h"

struct Measure
{
	Measure() {}
};

PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	Measure* measure = new Measure;
	*data = measure;
}

PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	Measure* measure = (Measure*)data;
}

PLUGIN_EXPORT double Update(void* data)
{
	Measure* measure = (Measure*)data;
	return 0.0;
}

PLUGIN_EXPORT void Finalize(void* data)
{
	Measure* measure = (Measure*)data;
	delete measure;
}

So there are four main sections in a plugin that control things. Initialize() which is always only executed once when the plugin is loaded or refreshed, Reload() which is also only executed when the plugin is loaded or refreshed OR when the plugin is updated IF DynamicVariables=1, Update() which is executed and returns the value each time the plugin is updated, and Finalize() which is only executed when the plugin is unloaded.

So in effect, DynamicVariables=1 causes both Reload() and Update() to be run on each update of the plugin, instead of just Update().

Measures in a skin work exactly the same way. There is literally no difference in behavior.

This provides for maximum flexibility, while tending to lean toward efficiency and performance.

All the options on a measure or meter are read and fully evaluated (resolving variables, formulas, section variables etc.) only when the skin is loaded or refreshed. Setting DynamicVariables=1 on a measure or meter forces this to be done on every update. That is not a bad thing, and you will use DynamicVariables a lot in Rainmeter, but it is marginally more expensive, and it's probably worth taking a second to consider if you really need it for the functionality you want.

What !SetOption does is in effect set DynamicVariables=1 on the measure or meter for the next update, then it is turned back off again. This can be a good way to dynamically change some option value, without permanently adding the slight overhead that DynamicVariables=1 has. So in effect you have a static option value, change it with !SetOption, and on the next update, that becomes the new static value.

The has nothing to do with when the measure or meter is updated though. In order to force an immediate update to go along with your !SetOption, use both.

LeftMouseUpAction=[!SetOption MyCalc Formula "(#MyVar#-5)"][!UpdateMeasure MyCalc][!UdateMeter MyResult][!Redraw]
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Re: Question on DynamicVariables=1

Yincognito » February 3rd, 2019, 10:23 pm

jsmorley wrote:
February 3rd, 2019, 8:45 pm
So there are four main sections in a plugin that control things. Initialize() which is always only executed once when the plugin is loaded or refreshed, Reload() which is also only executed when the plugin is loaded or refreshed OR when the plugin is updated IF DynamicVariables=1, Update() which is executed and returns the value each time the plugin is updated, and Finalize() which is only executed when the plugin is unloaded.
Many thanks for this precise explanation - that's helpful in understanding the whole process in Rainmeter. Sorry for the late reply, by the way.
jsmorley wrote:
February 3rd, 2019, 8:45 pm
So in effect, DynamicVariables=1 causes both Reload() and Update() to be run on each update of the plugin, instead of just Update(). That is not a bad thing, and you will use DynamicVariables a lot in Rainmeter, but it is marginally more expensive, and it's probably worth taking a second to consider if you really need it for the functionality you want.
That's the other reason why I left DynamicVariables=1 in my skins - I already had a few meters using it for tooltips' section variables, and you never know when you need to have dynamic variables enabled on a random change in the code.
jsmorley wrote:
February 3rd, 2019, 8:45 pm
What !SetOption does is in effect set DynamicVariables=1 on the measure or meter for the next update, then it is turned back off again.
That's precisely why I asked about !SetOption, after reading that plugins need to support DynamicVariables=1 in order for !SetOption to work for their options. Apparently I read the whole thing well between the lines.
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Re: Question on DynamicVariables=1

Yincognito » February 3rd, 2019, 10:50 pm

One last question if I may, as the last reply gave me an idea: if I use the last meter's OnUpdateAction to set back DynamicVariables=0 on all meters after initially having it set to 1, will this retain the last value of those dynamic variables (the way !SetOption does) or they will revert to the 0/"" "default" values? Something like doing what !SetOption does, but without using !SetOption (for the clarity reasons I mentioned earlier), if that makes any sense...
User avatar
jsmorley
Developer
Posts: 19245
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Question on DynamicVariables=1

jsmorley » February 4th, 2019, 3:15 am

Yincognito wrote:
February 3rd, 2019, 10:50 pm
One last question if I may, as the last reply gave me an idea: if I use the last meter's OnUpdateAction to set back DynamicVariables=0 on all meters after initially having it set to 1, will this retain the last value of those dynamic variables (the way !SetOption does) or they will revert to the 0/"" "default" values? Something like doing what !SetOption does, but without using !SetOption (for the clarity reasons I mentioned earlier), if that makes any sense...


I don't follow. How are you going to set the value of DynamicVariables without !SetOption?
Yincognito
Posts: 652
Joined: February 27th, 2015, 2:38 pm

Re: Question on DynamicVariables=1

Yincognito » February 4th, 2019, 3:20 am

jsmorley wrote:
February 4th, 2019, 3:15 am
I don't follow. How are you going to set the value of DynamicVariables without !SetOption?
No, I meant not using !SetOption to set the dynamic variables that I use in formulas, that's all. I didn't mean not using !SetOption at all.