It is currently March 28th, 2024, 3:24 pm

Eliminate unecessary disk io

Discuss the use of Lua in Script measures.
Post Reply
russdirks
Posts: 12
Joined: June 9th, 2016, 4:53 am

Eliminate unecessary disk io

Post by russdirks »

I've got an external program that generates dynamic data and stores it in a text file. I want to display this data in a gauge so I wrote a lua script to read that file and provide various items of that data to some measures. Since a number of the measures update at the same time, I was trying to detect that in the lua script and only read from disk once to try to be more efficient. Here is what I've got so far:

Code: Select all

[Rainmeter]
Update=1000

[Measure1]
Measure=Script
ScriptFile=#@#MVis.lua
UpdateDivider=5

[Measure2]
Measure=Script
ScriptFile=#@#MVis.lua
UpdateDivider=5
and the lua code:

Code: Select all

function Initialize()
	data = LoadData()
end

function Update()
	print(os.clock() - lastLoad)
	-- if we've done a load within the last 500ms, don't do another.
	if (os.clock() - lastLoad) > 0.5 then
		data = LoadData()
	end
	if SELF:GetName() == "Measure1" then
		return data["online"]
	elseif SELF:GetName() == "Measure2" then
		return data["temps"]
	end
end

function LoadData()
	local data = {}

	-- load the data

	lastLoad = os.clock()
	return data
end
It's not working though. LoadData gets called for each measure. The 'print' statement that I put in the Update function always prints approx. 4.988 or there-abouts. I'm guessing it is because each measure is processed by a separate thread, so they all see the same value for 'lastLoad'. Ideally I need a Mutex or a critical section, but I don't know if that is supported in the Rainmeter version of Lua.

Any ideas how I can accomplish this?

Edit: I tried setting the global update rate to 10 and the UpdateDivider to 500 and 501, respectively, for the two measures, but it is still doing the same thing.
russdirks
Posts: 12
Joined: June 9th, 2016, 4:53 am

Re: Eliminate unecessary disk io

Post by russdirks »

After some experimentation and research, I have come to realize that when multiple measures use the same Lua script, each measure actually has its own separate instance of the lua script, including the value of all global variables. I had assumed that the variables would be shared. (If I am wrong about any of this, please correct me.)

So it seems that it won't be possible for the Lua computations done for one measure to be made available to other measures.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Eliminate unecessary disk io

Post by jsmorley »

russdirks wrote:After some experimentation and research, I have come to realize that when multiple measures use the same Lua script, each measure actually has its own separate instance of the lua script, including the value of all global variables. I had assumed that the variables would be shared. (If I am wrong about any of this, please correct me.)

So it seems that it won't be possible for the Lua computations done for one measure to be made available to other measures.
You are correct. Each Script measure is a separate, unique, sandboxed instance of Lua.

Any "sharing" of information between them would have to be explicit "hand offs". That might be by having one Lua script write a file and the other read it, or having a Lua script use !bangs to set #Variables# or use !SetOption to set the value of Calc or String measures, that the other script could use. There is no direct way to share information between scripts. They are sandboxed.

Somewhat unrelated, but worth remembering, is that Lua scripts are not "re-entrant". The Initialize() function is executed and any values maintained when the script measure is created by Rainmeter, but is not updated or read again until the measure is destroyed and re-created (a skin refresh). All other functions in the script, Like Update() that is executed on each update of the measure in Rainmeter, or other functionName() that you might call with !CommandMeasure, are instantiated from scratch each time they are executed. Setting a variable to "1" in one update does not mean it will be "1" on the next update.
russdirks
Posts: 12
Joined: June 9th, 2016, 4:53 am

Re: Eliminate unecessary disk io

Post by russdirks »

jsmorley wrote:Any "sharing" of information between them would have to be explicit "hand offs". That might be by having one Lua script write a file and the other read it, or having a Lua script use !bangs to set #Variables# or use !SetOption to set the value of Calc or String measures, that the other script could use.
Yes, I had thought of doing something like that. I was worried about 2 things though: (maybe you can answer)
  1. The !SetVariable bang just writes to memory, right, not to my .ini file on disk? That would sort of defeat my goal of trying to save on disk I/O.
  2. Race conditions ... Is Rainmeter single threaded or multi-threaded?
jsmorley wrote:Somewhat unrelated, but worth remembering, is that Lua scripts are not "re-entrant". ... Setting a variable to "1" in one update does not mean it will be "1" on the next update.
Are you sure? I'm seeing something different. With the following test script ...

Code: Select all

function Initialize()
	lastClock = os.clock()
	msg = "Hello World!"
end

function Update()
	print(msg)
	print("Last clock=" .. lastClock .. ", current clock=" .. os.clock())
	lastClock = os.clock()
end
... I'm getting the following output in the log file :

Code: Select all

DBUG (12:45:03.893) : Hello World!
DBUG (12:45:03.893) : Last clock=17281.836, current clock=17281.837
DBUG (12:45:08.891) : Hello World!
DBUG (12:45:08.892) : Last clock=17281.838, current clock=17286.837
DBUG (12:45:13.893) : Hello World!
DBUG (12:45:13.895) : Last clock=17286.837, current clock=17291.84
DBUG (12:45:18.893) : Hello World!
DBUG (12:45:18.896) : Last clock=17291.841, current clock=17296.84
The "Hello World!" message is printed, and the value of the clock is remembered from the previous Update.
Post Reply