Creating Ruby time object causing garbage collection problem
I am an absolute newbie without even a computer science background. I am just a mechanical engineer trying to implement a way to remotely monitor the power output (and other output data) of the inverters in the solar power systems we install. So if I say anything exceedingly dumb, I apologize in advance.
I'm trying to write a little ruby program that will live in my ror website's database folder. Every 15 minutes (for as long as the system is online producing energy), I want it to poll the data from our customers' inverters (via TCPSocket connection to a gateway connected to customer inverter) and update my website's database file with the new data. The loop I have looks something like this:
last_min = Time.new.min
while(1) 开发者_JS百科do
tsec = Time.new.sec
tmin = Time.new.min
if ( ( tsec == 0 ) && ( tmin - last_min == 1 ) ) # test using one minute
# poll inverters, update database
last_min = tmin
end
end
When I ran it at first, it threw a Segmentation Fault error. Then i put GC.disable
up top and it worked fine (until I force quit only after a couple of min), but that was just to see if it was a garbage collection issue which it is and it seems to be the first creation of a time object that triggers the issue (throws the segmentation fault error). I know I obviously can't have garbage collection disabled for an infinite loop. But how do I "clean up after myself" with ruby? Can I free those time objects somehow at the end of every run through the loop? I saw a post about GC.start
, but couldn't quite understand how that works.
Also is there a way to run my program and see how much RAM it's using as it goes? I would appreciate any and all advice anyone could offer me here. (Including advice about the general architecture of the solar power output monitoring system I described in the beginning!)
I have already deeply benefited from looking at all of the posts on here in my journey thus far and I thank you in advance!
To force the garbage collection, just call GC.start
at the end of your loop. Anything that can be garbage collected will be garbage collected.
With that said, if you really just want an infinite loop to do something every minute (or 15 minutes), instead of comparing Time.now minutes and seconds, just make a call to sleep inside of your infinite loop.
loop do
poll_inverters_and_update_db
sleep 60
end
Since you mentioned you are using Rails, you may also want to look into delayed_job for doing this type of thing, or just setting up a cron job to execute every n minutes.
Sounds like an interesting project.
You only need one Time object per interval, since you can do arithmetic operations with times. For example:
t0 = Time.new
while(1) do
if ( Time.new - t0 >= 60 ) # test using one minute
# poll inverters, update database
t0 = Time.new
end
end
Then you don't need to worry about GC issues.
PS. +1 for using delayed_job or some other way of putting this in its own thread, or cron if you can run it as its own process, since a loop like this or using sleep() will block everything else.
精彩评论