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

Trailing throttle syncs to front-end #1036

Merged
merged 6 commits into from
Apr 1, 2021
Merged

Trailing throttle syncs to front-end #1036

merged 6 commits into from
Apr 1, 2021

Conversation

pankgeorg
Copy link
Collaborator

@pankgeorg pankgeorg marked this pull request as draft March 27, 2021 17:43
@pankgeorg
Copy link
Collaborator Author

Converting this to draft as I would like to check whether we can add a lock to the function call; I don't trust concurrency 🎈✨⭐

@pankgeorg
Copy link
Collaborator Author

pankgeorg commented Mar 27, 2021

Added 'thread safety', which means that the function cannot be running by two threads simultaneously.
The caveat is that (in tightly called sequences) the timeout time gets extended by the time the function is running.

The last thing to consider is, do mutations that may happen 'simultaneously' matter? should every throttled function call get its own copy of the state??

@fonsp
Copy link
Owner

fonsp commented Mar 29, 2021

In the first paragraph of your comment, aren't you saying that the second paragraph is not possible?

@fonsp
Copy link
Owner

fonsp commented Mar 29, 2021

Can you add some basic tests with sleep to make sure that the basic throttling is working? The code got a bit too complicated to just review it. E.g.

x = Ref(0)

function f()
	x[] += 1
end
f()
@test x[] == 1

dt = 1/100
ft, stop = throttled(f, dt; initial_cooldown=true)

for x in 1:10
	ft()
end
@test x[] == 1
sleep(2dt)
@test x[] == 2

for x in 1:10
	ft()
end
@test x[] == 3
sleep(2dt)
@test x[] == 4


for x in 1:5
	ft()
	sleep(1.5dt)
end
@test x[] == 9
sleep(2dt)
@test x[] == 9

###

ft()
ft()
@test x[] == 10
stop()
@test x[] == 11
sleep(2dt)
@test x[] == 11

@pankgeorg
Copy link
Collaborator Author

pankgeorg commented Mar 29, 2021

In the first paragraph of your comment, aren't you saying that the second paragraph is not possible?

Not exactly - I'm saying that if f is throttled by the function, and has argument1, argument2 as arguments, then, f will never run when f runs. (first paragraph)

BUT if g is mutating argument1, argument2 there is no guarantee that f and g don't run such as they corrupt each other's data. (second paragraph)

I'm not even sure if that's possible by Julia's thread model (since our f doesn't yield, but it may do some network stuff that counts as 'idle'??)

The thing is that we'll probably need to be locking the resource (argument1, argument2 = session, notebook).

Can you add some basic tests with sleep to make sure that the basic throttling is working? The code got a bit too complicated to just review it. E.g.

Of course! I have a notebook that does this here: https://github.com/pankgeorg/spam/blob/main/throttled.jl, I'll convert to a test

@fonsp
Copy link
Owner

fonsp commented Mar 29, 2021

Why does f take arguments? It makes more sense to drop that feature

@@ -47,7 +47,8 @@ function run_reactive!(session::ServerSession, notebook::Notebook, old_topology:
end

# Send intermediate updates to the clients at most 20 times / second during a reactive run. (The effective speed of a slider is still unbounded, because the last update is not throttled.)
send_notebook_changes_throttled = throttled(1.0/20, 0.0/20) do
# flush_send_notebook_changes_throttled,
send_notebook_changes_throttled, flush_notebook_changes = throttle(1.0/20; leading=false, trailing=true) do
send_notebook_changes!(ClientRequest(session=session, notebook=notebook))
Copy link
Collaborator Author

@pankgeorg pankgeorg Mar 29, 2021

Choose a reason for hiding this comment

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

This code will run at most once per 1/20 sec, @async.
BUT there is no guarantee I can think of that code that mutates (notebook, session) will not run right before/right after/inbetween.

e.g. runsingle! at line 80-something

@fonsp

This comment has been minimized.

@pankgeorg
Copy link
Collaborator Author

Why does f take arguments? It makes more sense to drop that feature

The feature is not related; the () -> send_notebook_changes!(ClientRequest(session=session, notebook=notebook)) holds references to session and notebook.

locking the resource (argument1, argument2 = session, notebook).

We already lock notebook, right?

take!(notebook.executetoken)

all these functions all hold the lock, I think.

@fonsp
Copy link
Owner

fonsp commented Mar 29, 2021

The feature is not related

I see, I can try to think about the thread safe stuff tomorrow with a CLEAR brain :) It does seem like the code would be simpler if you deleted the args, kwargs, and result features. Because then, later could just be a boolean, for example.

@fonsp fonsp changed the title Throttle syncs to front-end Trailing throttle syncs to front-end Apr 1, 2021
@fonsp fonsp marked this pull request as ready for review April 1, 2021 19:26
@fonsp fonsp merged commit 79496d6 into main Apr 1, 2021
@fonsp fonsp deleted the throttle-fix branch April 1, 2021 19:26
pankgeorg added a commit that referenced this pull request Apr 25, 2021
Co-authored-by: Fons van der Plas <fonsvdplas@gmail.com>
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