Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TimerTask improvements #791

Merged
merged 4 commits into from
Jun 27, 2018
Merged

TimerTask improvements #791

merged 4 commits into from
Jun 27, 2018

Conversation

davidor
Copy link
Contributor

@davidor davidor commented Jun 26, 2018

This PR implements several improvements in the TimerTask module:

  1. Adapts the module to use the new GC module introduced in the previous PR Workaround to make __gc work on tables #790
  2. Fixes a bug that prevents the task from being garbage collected. This is done by avoiding passing self.
  3. Fixes a bug when calculating the delay when scheduling the next task.

@davidor davidor requested a review from a team as a code owner June 26, 2018 16:17
@davidor davidor force-pushed the use-gc-module-in-timer-task branch from 69d3c58 to fd773c0 Compare June 26, 2018 16:18
@davidor davidor changed the title Adapt TimerTask to use new GC module TimerTask improvements Jun 26, 2018
res_mt.__index = _M
return res_mt
return {
__gc = function() _M.unregister_task(id) end,
Copy link
Contributor

@mikz mikz Jun 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't there be generic __gc metamethod ? To avoid allocating extra table for each timer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so because it needs the 'id'.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it can get the id from self no ? It will get the table as first argument, so it can take the id from there.

end

schedule_next(self)
local t_diff = ngx_now() - t_start
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I we are doing this, I'd rather go for monotonic time. It is not that hard to do:
https://github.com/3scale/apicast/blob/ea7966080dce42eb0d92b9fda85c99de8700e2ca/benchmark/template.lua#L14-L19

local t_diff = ngx_now() - t_start

local delay_for_next = interval - t_diff
if delay_for_next < 0 then delay_for_next = 0 end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think LuaJIT recommends using math.max instead of conditions (as they can't be JITed).

http://wiki.luajit.org/Numerical-Computing-Performance-Guide

schedule_next(self)
local t_diff = ngx_now() - t_start

local delay_for_next = interval - t_diff
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really needed?
I think it is just fine to delay the execution. Documenting it is way easier than doing this. Also it could end up in situation when are two called immediately after each other because they took more than the delay.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think from a user perspective is more natural to expect a consistent reporting every X seconds. But there are no guarantees anyway because some reports might take more than the interval specified in the config. I don't think it's too important, we can remove it to simplify this a bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer it to be simpler. It can be documented pretty easily.

For the record, ngx.timer.every behaves quite stupidly and will schedule timer every N seconds regardless how long the timer takes.

@davidor davidor force-pushed the use-gc-module-in-timer-task branch 3 times, most recently from e027d51 to be4556f Compare June 27, 2018 09:26
@davidor
Copy link
Contributor Author

davidor commented Jun 27, 2018

Comments addressed, some of them no longer apply after removing #791 (comment)

_M.unregister_task(self.id)
end

local function mt()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now there is no need to allocate a metatable per instance and can just share one, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

davidor added 4 commits June 27, 2018 15:16
TimerTask is now built calling GC.set_metatable_gc. That method returns
an object for which type() returns "userdata". Luassert only allows
creating stubs on objects for which type() returns "table".
So instances can be garbage-collected
@davidor davidor force-pushed the use-gc-module-in-timer-task branch from be4556f to 998ed26 Compare June 27, 2018 13:16
Copy link
Contributor

@mikz mikz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@davidor davidor merged commit 470572a into master Jun 27, 2018
@davidor davidor deleted the use-gc-module-in-timer-task branch June 27, 2018 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants