It is currently April 16th, 2024, 6:19 pm

Debloat my code

Get help with creating, editing & fixing problems with skins
Vaile
Posts: 2
Joined: August 17th, 2021, 8:37 am

Debloat my code

Post by Vaile »

Hi, I'm super new to this coding thing and I was able to make a skin by cobbling together what other people have done but it uses a ton of CPU processing power. It's a fairly simple launcher app but my CPU usage rails up to 40%, I know it's because of the skin I made because if I unload it my CPU usage will go back down to >10% Idle.Anyways If anyone could take a look at it and tell me what i should do to make it have less of an impact on my system that would be a huge help. Thanks
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Debloat my code

Post by Yincognito »

Vaile wrote: August 21st, 2021, 3:07 am Hi, I'm super new to this coding thing and I was able to make a skin by cobbling together what other people have done but it uses a ton of CPU processing power. It's a fairly simple launcher app but my CPU usage rails up to 40%, I know it's because of the skin I made because if I unload it my CPU usage will go back down to >10% Idle.Anyways If anyone could take a look at it and tell me what i should do to make it have less of an impact on my system that would be a huge help. Thanks
Indeed. The high CPU usage happens because, like I explained in another thread, doing image transformations (like rotating, resizing, etc.) at a low update rate will take a lot of CPU. What happens in your skin is:
- you are resizing images in the Photoshop, Premiere, MediaEncoder and Adobe meters, simply because you set the W and H of the meters to a different value than what the associated image resolution is (e.g. at 160x160, with the image size being 512x512)
- you are using a low (and invalid as well, technically) update rate in the [Rainmeter] section, at Update=10, aka 10 milliseconds. It's low because you need the animation to happen, and it's more or less invalid because the lowest update rate there is 16 milliseconds (which is the actual update rate you have in your skin, as Rainmeter automatically sets it to the nearest "valid" value)

You can easily test whether I'm right or not simply by commenting out with ; at the start of the line the W and H of those meters mentioned above, like (I also made other minor corrections / shuffling of your code, by the way):

Code: Select all

[Variables]
MOVE=80

[Rainmeter]
Update=25
DynamicWindowSize=1
AccurateText=1

---Measures---

[MovingMeasure]
Disabled=1
Measure=Calc
Formula=(Clamp(MovingMeasure+20,0,#MOVE#))

---Meters---

[Menu]
Group=Hover
Hidden=1
Meter=Shape
X=152
Y=-26
Shape=Rectangle 0,0,118,458 | Fill Color 0,0,0,0 | Stroke Color 0,0,0,0 | Rotate 45
AntiAlias=1
LeftMouseUpAction=[!HideMeterGroup Hover][!UpdateMeterGroup Hover][!Refresh]

[spacer]
Hidden=1
Meter=Image
X=250
Y=2
W=160
H=160

[Photoshop]
Meter=Image
X=-[MovingMeasure]r
Y=[MovingMeasure]
;W=160
;H=160
ImageName=#@#Images\Photoshop.png
DynamicVariables=1

[Premiere]
Meter=Image
X=-[MovingMeasure]r
Y=([MovingMeasure]*2)
;W=160
;H=160
ImageName=#@#Images\Premiere.png
DynamicVariables=1

[MediaEncoder]
Meter=Image
X=-[MovingMeasure]r
Y=([MovingMeasure]*3)
;W=160
;H=160
ImageName=#@#Images\MediaEncoder.png
DynamicVariables=1

[Adobe]
Meter=Image
ImageName=#@#Images\Adobe.png
X=250
Y=0
;W=160
;H=160

[AppTray]
Meter=Shape
X=278
Y=28
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,0| Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Adobe ImageName "#@#Images\Adobe2.png"][!UpdateMeter Adobe][!Redraw]
MouseLeaveAction=[!SetOption Adobe ImageName "#@#Images\Adobe.png"][!UpdateMeter Adobe][!Redraw]
LeftMouseUpAction=[!ShowMeterGroup Hover][!ToggleMeasure MovingMeasure][!UpdateMeter][!Redraw]

[Square1]
Group=Hover
Hidden=1
Meter=Shape
X=196
Y=109
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,0 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Photoshop ImageName "#@#Images\Photoshop2.png"][!UpdateMeter Photoshop][!Redraw]
MouseLeaveAction=[!SetOption Photoshop ImageName "#@#Images\Photoshop.png"][!UpdateMeter Photoshop][!Redraw]
LeftMouseUpAction=[!HideMeterGroup Hover][!UpdateMeterGroup Hover][!Redraw]["Photoshop.exe"]

[Square2]
Group=Hover
Hidden=1
Meter=Shape
X=-82r
Y=-55R
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,0 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Premiere ImageName "#@#Images\Premiere2.png"][!UpdateMeter Premiere][!Redraw]
MouseLeaveAction=[!SetOption Premiere ImageName "#@#Images\Premiere.png"][!UpdateMeter Premiere][!Redraw]
LeftMouseUpAction=[!HideMeterGroup Hover][!UpdateMeterGroup Hover][!Redraw]["Adobe Premiere Pro.exe"]

[Square3]
Group=Hover
Hidden=1
Meter=Shape
X=-82r
Y=-55R
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,0 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption MediaEncoder  ImageName "#@#Images\MediaEncoder2.png"][!UpdateMeter MediaEncoder][!Redraw]
MouseLeaveAction=[!SetOption MediaEncoder ImageName "#@#Images\MediaEncoder.png"][!UpdateMeter MediaEncoder][!Redraw]
LeftMouseUpAction=[!HideMeterGroup Hover][!UpdateMeterGroup Hover][!Redraw]["Adobe Media Encoder.exe"]
If you try the above code, you'll notice that the CPU usage drops to the "normal" level. Obviously, the images being larger, stuff won't work, so all you have to do is resize your images from Photoshop to the desired 160x160 resolution, then use them without setting their W and H, like above. Since we're at it, you can easily do multiple image resizing in Photoshop by recording your Action in Menu / Window / Actions (basically doing Menu / Image / Image Size... and resizing to 160x160), then from Menu / File / Automate / Batch... play your previously recorded actions on your ...@Resources\images folder and choosing Save & Close in the Destination field:
Resize.jpg
That being said, what you did in the skin can be done using the ActionTimer plugin as well. The advantage to that is that your skin will be able to use a "normal" update rate of either 1000 or even -1, while ONLY the ActionTimer actions will "play" at the lower update rate required for the animation effect. The conversion should be relatively easy to do, but since you're new to the whole thing you can ask for help at any time, if you want to. ;-)
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Vaile
Posts: 2
Joined: August 17th, 2021, 8:37 am

Re: Debloat my code

Post by Vaile »

Brilliant, thanks for the feedback. I'll take your advice and look into the ActionTimer Plugin, do you think this will lower the CPU usage any further or will I just have to test it out to see. Sometimes this coding stuff makes my brain hurt, It's both frustrating and at the same time rewarding when you get your code working but as this post demonstrates sometimes finessing the code just takes experience. Thanks again
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Debloat my code

Post by Yincognito »

Vaile wrote: August 24th, 2021, 2:02 am Brilliant, thanks for the feedback. I'll take your advice and look into the ActionTimer Plugin, do you think this will lower the CPU usage any further or will I just have to test it out to see. Sometimes this coding stuff makes my brain hurt, It's both frustrating and at the same time rewarding when you get your code working but as this post demonstrates sometimes finessing the code just takes experience. Thanks again
Glad it helped. ;-)
ActionTimer's CPU usage is just a bit higher than the low skin update rate method, but:
- it's noticeable only in more complex scenarios
- it only happens when the actual animation happens, instead of during the entire period the skin is loaded, like the low update rate method (assuming, of course, that the latter is in its "normal", unoptimized form)

Personally, I prefer the optimized form (which basically means setting UpdateDivider=-1 options on everything and only update or redraw things on demand, when absolutely necessary) of the low update rate method, but that's mainly because it behaves slightly better on my oftenly used endless animations. For your case of a short, user triggered animation, the ActionTimer method fits like a glove. I'm on mobile now so can't adapt the code, but I'll do it when I'm back to my computer, if by any chance you find it too hard to wrap your head around the concept.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Debloat my code

Post by Yincognito »

Vaile wrote: August 24th, 2021, 2:02 amI'll take your advice and look into the ActionTimer Plugin, do you think this will lower the CPU usage any further or will I just have to test it out to see.
In case you didn't manage to figure it out by now, this is what an ActionTimer approach would look like:

Code: Select all

[Variables]
Move=80
Step=20
Count=4
Wait=25
Offset=0
Direction=-1

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

---Measures---

[Slider]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Hide | Wait #Wait# | Repeat Slide,#Wait#,#Count# | Wait #Wait# | Show | Wait #Wait#
Slide=[!SetVariable Offset (Clamp(#Offset#+#Direction#*#Step#,0,#Move#))][!UpdateMeasure Slider][!UpdateMeter *][!Redraw]
Hide=[!SetOptionGroup Hover Hidden 1][!UpdateMeter *][!Redraw]
Show=[!SetOptionGroup Hover Hidden (#Direction#>0?:0:1)][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

---Meters---

[Spacer]
Hidden=1
Meter=Image
X=250
Y=2
W=160
H=160

[Photoshop]
Meter=Image
X=-#Offset#r
Y=#Offset#
ImageName=#@#Images\Photoshop.png
DynamicVariables=1

[Premiere]
Meter=Image
X=-#Offset#r
Y=(#Offset#*2)
ImageName=#@#Images\Premiere.png
DynamicVariables=1

[MediaEncoder]
Meter=Image
X=-#Offset#r
Y=(#Offset#*3)
ImageName=#@#Images\MediaEncoder.png
DynamicVariables=1

[Square1]
Group=Hover
Hidden=1
Meter=Shape
X=([Photoshop:X]+(160-110)/2)
Y=([Photoshop:Y]+(160-110)/2)
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,1 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Photoshop ImageName "#@#Images\Photoshop2.png"][!UpdateMeter *][!Redraw]
MouseLeaveAction=[!SetOption Photoshop ImageName "#@#Images\Photoshop.png"][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!SetVariable Direction (-#Direction#)][!UpdateMeasure Slider][!CommandMeasure Slider "Stop 1"][!CommandMeasure Slider "Execute 1"]["Photoshop.exe"]
DynamicVariables=1

[Square2]
Group=Hover
Hidden=1
Meter=Shape
X=([Premiere:X]+(160-110)/2)
Y=([Premiere:Y]+(160-110)/2)
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,1 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Premiere ImageName "#@#Images\Premiere2.png"][!UpdateMeter *][!Redraw]
MouseLeaveAction=[!SetOption Premiere ImageName "#@#Images\Premiere.png"][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!SetVariable Direction (-#Direction#)][!UpdateMeasure Slider][!CommandMeasure Slider "Stop 1"][!CommandMeasure Slider "Execute 1"]["Adobe Premiere Pro.exe"]
DynamicVariables=1

[Square3]
Group=Hover
Hidden=1
Meter=Shape
X=([MediaEncoder:X]+(160-110)/2)
Y=([MediaEncoder:Y]+(160-110)/2)
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,1 | Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption MediaEncoder  ImageName "#@#Images\MediaEncoder2.png"][!UpdateMeter *][!Redraw]
MouseLeaveAction=[!SetOption MediaEncoder ImageName "#@#Images\MediaEncoder.png"][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!SetVariable Direction (-#Direction#)][!UpdateMeasure Slider][!CommandMeasure Slider "Stop 1"][!CommandMeasure Slider "Execute 1"]["Adobe Media Encoder.exe"]
DynamicVariables=1

[Adobe]
Meter=Image
ImageName=#@#Images\Adobe.png
X=250
Y=0

[AppTray]
Meter=Shape
X=278
Y=28
Shape=Rectangle 0,0,110,110 | Fill Color 0,0,0,0| Stroke Color 0,0,0,0 | Rotate 45
MouseOverAction=[!SetOption Adobe ImageName "#@#Images\Adobe2.png"][!UpdateMeter *][!Redraw]
MouseLeaveAction=[!SetOption Adobe ImageName "#@#Images\Adobe.png"][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!SetVariable Direction (-#Direction#)][!UpdateMeasure Slider][!CommandMeasure Slider "Stop 1"][!CommandMeasure Slider "Execute 1"]
DynamicVariables=1
assuming you're already using the 160x160 resize images in your ...\@Resources\images folder as advised:
images.rar
The key is the [Slider] measure, where increasing or decreasing the #Offset# variable (basically, the equivalent of your old [MovingMeasure] used in setting the coordinates of the images, but as a variable) for #Count# times and at #Wait# millisecond intervals, coupled with updating the relevant measures / meters, does the animation. Its execution is triggered by a [!CommandMeasure Slider "Execute 1"] bang in the appropriate mouse actions (we execute 1, aka ActionList1 from the measure) and its stopping by the similarly formatted [!CommandMeasure Slider "Stop 1"] bang (a safe thing to do is to always stop whatever actions are "playing" before executing them again, hence the [!CommandMeasure Slider "Stop 1"][!CommandMeasure Slider "Execute 1"] bang sequence).

I could have created 2 action lists, i.e. ActionList1 and ActionList2 and have 2 associated names for the singular operations whose repeating made up those actions, i.e. SlideIn and SlideOut, but to make the code more compact I chose to use a #Direction# variable to indicate whether the slide was "in" (i.e. Direction=-1) or "out" (i.e. Direction=1) and to toggle between those values in the meters' mouse actions - and since the direction is multiplied with the step when adding to the offset during sliding, this has the effect of either decreasing or increasing the offset value with a number of step pixels. I only added the Hide and Show actions to prevent the reaction to mouse actions while sliding is still running, but if you're not bothered by it, you can comment out the Hidden=1 in the meters and change the action list to the bare ActionList1=Repeat Slide,#Wait#,#Count# | Wait #Wait#.

Other than that, you can play with the values of the variables in the [Variables] section, in order to tweak / adjust the extent (Move), the rate (Step), the frames (Count) and the speed (Wait) of the animation. For example, you can set Step to 1 and Count to 80 (normally, #Step#*#Count# should yield the #Move# value, but that's not absolutely required) to have a pixel by pixel slow-motion, you can change the Wait time to similarly speed up or slow down playing the animation steps, or you can decrease or increase the Move amount to place meters closer or further away from each other (you'd have to adjust the [Spacer], [Adobe] and [AppTray] positions to make things fit the skin though, as I didn't bothered with it, even if I already adjusted the shape positions so that they follow the images in their slide movement).

P.S. You can add an UpdateDivider=-1 to all meters (or set a DefaultUpdateDivider=-1 in the [Rainmeter] section) if you want to squeeze the most you can and make your skin very strict on CPU usage, but then, things already update once a second in [Rainmeter] so this will be low enough on CPU anyway, at least if the images or the skin aren't huge in size.
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth