kani icon indicating copy to clipboard operation
kani copied to clipboard

BLOCKED: Add kani::spawn and an executor to the Kani library

Open fzaiser opened this issue 3 years ago • 1 comments

Description of changes:

This adds an executor (scheduler for async futures) to the Kani library, thus supporting kani::spawn as a replacement for tokio::spawn.

It also includes kani::yield_now which is similar to tokio::yield_now.

Resolved issues:

Resolves #1504

Call-outs:

Blocked on #1588: This cannot currently be merged because linking the Kani library is broken (just like the standard library).

Testing:

  • How is this change tested? Additional regression tests.

  • Is this a refactor change? No.

Checklist

  • [x] Each commit message has a non-empty body, explaining why the change was made
  • [x] Methods or procedures are documented
  • [x] Regression or unit tests are included, or existing tests cover the modified code
  • [x] My PR is restricted to a single feature or bugfix

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

fzaiser avatar Sep 08 '22 20:09 fzaiser

~TODO: add check that the number of tasks is less than MAX_TASKS.~ Done

fzaiser avatar Sep 17 '22 02:09 fzaiser

With the MIR linker, this is no longer blocked! Ready for review @danielsn @celinval

fzaiser avatar Oct 31 '22 16:10 fzaiser

The latest CI run failed for spawn.rs: CBMC failed with status 137. Exit code 137 means that it ran out of memory, I think.

@celinval: could this be related to the new linker? If the scheduling code is in the same file, like in manual_spawn.rs, everything finishes quickly. (#1818 seems to be related?)

fzaiser avatar Nov 01 '22 11:11 fzaiser

Yes,

The latest CI run failed for spawn.rs: CBMC failed with status 137. Exit code 137 means that it ran out of memory, I think.

@celinval: could this be related to the new linker? If the scheduling code is in the same file, like in manual_spawn.rs, everything finishes quickly. (#1818 seems to be related?)

Yes, the main purpose of the new linker was to get rid of the undefined symbols from the standard library. Fixing this issue meant that some models got bigger and harder to process.

celinval avatar Nov 02 '22 20:11 celinval

Yes, the main purpose of the new linker was to get rid of the undefined symbols from the standard library. Fixing this issue meant that some models got bigger and harder to process.

@celinval That makes sense. What I don't get is that it works fine if all the scheduling code is in the same file, see manual_spawn.rs. This file uses the same code that this PR puts into the Kani library, but puts that code directly into the file with the harness. That seems to verify much more quickly, which does not make sense to me. Do you know why?

fzaiser avatar Nov 03 '22 10:11 fzaiser

Yes, the main purpose of the new linker was to get rid of the undefined symbols from the standard library. Fixing this issue meant that some models got bigger and harder to process.

@celinval That makes sense. What I don't get is that it works fine if all the scheduling code is in the same file, see manual_spawn.rs. This file uses the same code that this PR puts into the Kani library, but puts that code directly into the file with the harness. That seems to verify much more quickly, which does not make sense to me. Do you know why?

I see. Let me take a look, but it is possible that moving the file into a different crate changed how rustc optimizes the code.

celinval avatar Nov 03 '22 18:11 celinval

I looked at the issue you mentioned, and I think the difference is due to the second harness in spawn.rs (nondeterministic_schedule). If you remove it, the time and problem size is basically the same independent on the location of the scheduling code.

The interesting thing is that the time is pretty bad even if you run --harness deterministic_schedule. That's probably because we perform reachability analysis for all harnesses at the same time, instead of doing them separately. My guess is that CBMC slicer is not smart enough to prune the closures out of the model due to a more conservative pointer analysis.

You can see a similar effect with the --legacy-linker by just moving the scheduling code to spawn.rs. If you run kani --harness deterministic_schedule --legacy-linker with and without the second harness co-located in spawn.rs, the times are drastically different. In my machine, Kani verification succeeds after 70ish seconds if you remove the second harness, but it doesn't finish under 5min if you add the second one.

celinval avatar Nov 03 '22 18:11 celinval

@celinval Thanks for that investigation. I've removed the nondeterministic test for now to make CI (hopefully) pass. I've also converted a bool to an enum and improved the documentation.

fzaiser avatar Nov 04 '22 16:11 fzaiser

Hm, seems like CI still runs out of memory. I'm not sure what to do about that. Any ideas?

fzaiser avatar Nov 04 '22 17:11 fzaiser

Can you run it locally and measure the memory consumption so we have an idea on how bad the problem is?

celinval avatar Nov 04 '22 19:11 celinval

Can you run it locally and measure the memory consumption so we have an idea on how bad the problem is?

@celinval, I just tried that with the second harness (the nondeterministic one) completely removed, so #1855 does not apply. It OOMed after 1 hour, maximum resident set size was about 15 GB. (My computer has 16 GB RAM, so it took up almost all the available memory.)

Should I open a bug about this? It makes no sense to me that it would take so much longer just because the code is in the Kani library instead of the same file. What do you think? cc @danielsn

fzaiser avatar Nov 08 '22 09:11 fzaiser

Can you run it locally and measure the memory consumption so we have an idea on how bad the problem is?

@celinval, I just tried that with the second harness (the nondeterministic one) completely removed, so #1855 does not apply. It OOMed after 1 hour, maximum resident set size was about 15 GB. (My computer has 16 GB RAM, so it took up almost all the available memory.)

Should I open a bug about this? It makes no sense to me that it would take so much longer just because the code is in the Kani library instead of the same file. What do you think? cc @danielsn

Sure. You can open a bug.

celinval avatar Nov 08 '22 17:11 celinval

Submitted #1876. This PR is blocked on this issue.

fzaiser avatar Nov 09 '22 18:11 fzaiser

The test is passing! Now that vectors are faster, I want to change this to use vectors instead of arrays before merging.

fzaiser avatar Dec 16 '22 17:12 fzaiser

@danielsn @celinval This should be ready for another round of review. Note that we now use vectors instead of arrays because they have gotten fast enough. Two questions to decide before merging:

  1. The scheduling strategies NondeterministicScheduling and NondetFairScheduling are currently untested (commented out in spawn.rs and manual_spawn.rs) because they take too long. (I stopped them after half an hour and taking 15 GB of RAM.) Should we make them private given that they're untested? I would prefer to leave them in (and maybe hide their documentation), so users can still experiment with them if they absolutely want to.
  2. Should we remove manual_spawn.rs? Since the two versions now take almost no time (but see #1876), it may be redundant to have both.

fzaiser avatar Dec 16 '22 19:12 fzaiser

Our libraries don't usually have much logic into them, so there's not much to test. In these news APIs, I think we should test the scheduler logic. We should either have proofs for them or just concrete tests. An error in the scheduler could result in a soundness issue, right?

celinval avatar Dec 22 '22 01:12 celinval

@celinval: There is a proof harness using the scheduler (with the RoundRobin strategy) in spawn.rs. What additional tests or properties to prove do you have in mind?

The two nondeterministic scheduling strategies can only be tested in Kani proof harnesses, not in unit tests (because they use kani::any()). But even simple proof harnesses using them take a long time and lots of RAM. Altogether, this means they should not be included if you want them to be tested. Did I understand this correctly? (Another option to consider would be to include them, but hide their documentation. So users could still experiment with them, but we'd consider them "unstable".)

fzaiser avatar Dec 22 '22 16:12 fzaiser

Can you take advantage of the concrete playback infrastructure for injecting concrete values for testing purpose?

I do worry about the scalability. If we can't write simple harnesses with the nondeterministic strategies, what value do we get from adding them to the Kani library at this point?

celinval avatar Dec 23 '22 05:12 celinval

That's a good point. I have removed the nondeterministic scheduling strategies. No only the RoundRobin strategy is included. (And there's a test for it.)

fzaiser avatar Dec 23 '22 13:12 fzaiser

That's a good point. I have removed the nondeterministic scheduling strategies. No only the RoundRobin strategy is included. (And there's a test for it.)

But wouldn't the non-deterministic schedules be required for soundness? They might be impractical right now, but perhaps there is a way to make them tractable in future?

tautschnig avatar Jan 03 '23 12:01 tautschnig

That's a good point. I have removed the nondeterministic scheduling strategies. No only the RoundRobin strategy is included. (And there's a test for it.)

But wouldn't the non-deterministic schedules be required for soundness? They might be impractical right now, but perhaps there is a way to make them tractable in future?

Users can still create non-deterministic schedules and I think we should still keep an implementation in our benchmarks to know when they become practical, so we know it's time to add them.

I just don't think they should be in the Kani library until then. Specially since it cannot be tested at all today.

celinval avatar Jan 04 '23 21:01 celinval

Hi folks, what is the status of this PR?

rahulku avatar Jan 09 '23 21:01 rahulku

@rahulku I'll address the comments in the next few days.

fzaiser avatar Jan 10 '23 19:01 fzaiser

@celinval Thanks for your patience. Please take another look when you have time.

fzaiser avatar Feb 13 '23 13:02 fzaiser

@celinval I renamed the function spawnable_block_on to block_on_with_spawn as I think this name is clearer. ("spawnable" sounds like "can be spawned" instead of "can spawn")

If you don't have any other concerns, this should be ready to be merged.

fzaiser avatar Feb 15 '23 02:02 fzaiser

@danielsn @celinval friendly reminder :)

fzaiser avatar Feb 27 '23 09:02 fzaiser

@dsn @celinval friendly reminder :)

Sorry about that. Let me take a look

celinval avatar Feb 28 '23 16:02 celinval

Hi @fzaiser, I think this is good to go, except that I think we should add a mechanism to guard this code under a unstable flag. Let me just sketch something quick and we can merge this. Thanks!

celinval avatar Mar 01 '23 00:03 celinval

@fzaiser I created https://github.com/model-checking/kani/pull/2281 to get some feedback. Feel free to add comments there, but it should be a very quick change (famous last words).

celinval avatar Mar 08 '23 02:03 celinval

I created https://github.com/model-checking/kani/pull/2373 to add the unstable attribute and I'm planning to create another one to enforce the opt-in model.

Once https://github.com/model-checking/kani/pull/2373 is merged, I believe you can just tag the public APIs from this PR as unstable and we can merge these changes.

celinval avatar Apr 13 '23 23:04 celinval