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

Added SMT query hashes to hints to skip unchanged queries. #1257

Merged
merged 19 commits into from
Sep 29, 2017

Conversation

wintersteiger
Copy link

@nikswamy: the basic functionality is in place. Whenever the hashes match, it reports Query-stats ... succeeded (with hint) ... statistics={fstar_cache_hit=1}. It will also read old hints and then update them with hashes when --record_hints is on. It will use hashes whenever --use_hints is on, but I suppose it would be a good idea to add a command-line parameter to "opt in".

@wintersteiger wintersteiger self-assigned this Sep 21, 2017
@nikswamy
Copy link
Collaborator

Hi Christoph,

Many thanks for this feature.

In its current form, the PR is very hard to review since it contains many auto-generated files (.ml, .hints etc.)

Do you think you could submit another version of the PR with just the changes that actually need to be reviewed?

As for timing: I would wait for the ongoing Everest merge to stabilize and then try to update our projects and all hints to use this feature.

A question: will it possible to re-use old hint files with this feature turned off (i.e., just --use_hints with old hint files). Or, are we forced to upgrade all hint files as soon as this feature lands?

Thanks,
Nik

@wintersteiger
Copy link
Author

Agreed, it's a bit of a mess at the moment. I checked in new snapshot files because the extraction that worked perfectly fine on my machine didn't go through the CI for reasons that weren't obvious from the log files. I may have been using a different version of OCaml or some such thing.

Feature-wise, yes, old hint files will be read in exactly the same way as before when --use_hints is on. They will only be upgraded with the extra hash field when --record_hints is on. I also added --use_hint_hashes so the by default the behavior is exactly the same as before. Something's still wrong with that flag though, so don't merge just yet.

@nikswamy
Copy link
Collaborator

We've completed the Everest merge of last week. So, I'd be happy to have this feature completed and merged in as soon as you're done.

@wintersteiger
Copy link
Author

Working on this, should be done by the end of today!

@wintersteiger wintersteiger force-pushed the cwinter_query_hashes branch 2 times, most recently from 0f0bdfa to 405e21e Compare September 27, 2017 18:55
@wintersteiger
Copy link
Author

Features are there, but the OCaml extraction still won't work on the CI machine and I'm not getting any useful error messages. Apparently, the snapshot code extracts different code from the same sources when run on the CI machine, but so far I wasn't able to determine why.

@cpitclaudel
Copy link
Contributor

Nik, there's a dropdown in the Github UI that allows you to pick which commits to display :) Just exclude the snapshot commit.

@cpitclaudel
Copy link
Contributor

I'm excited about this feature :) IIUC, it's essentially an implementation of #1140, right?

How well will this work with the interactive mode? Are the caches constructed as we go, so that reprocessing the same query will now be much faster? That would be particularly nice.

@@ -766,6 +768,11 @@ let rec specs () : list<Getopt.opt> =
"Use a previously recorded hints database for proof replay");

( noshort,
"use_hint_hashes",
ZeroArgs (fun () -> mk_bool true),
Copy link
Contributor

Choose a reason for hiding this comment

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

I've just merged a change to master that will conflict with this line. The fix is to use Const (mk_bool true) instead of ZeroArgs (mk_bool true)

Copy link
Author

Choose a reason for hiding this comment

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

Did you rename/remove ZeroArgs? I'll have to re-merge with master anyways, so will be fixed imminently.

Copy link
Contributor

Choose a reason for hiding this comment

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

I added a layer on top of ZeroArgs / OneArg. Const gets interpreted into ZeroArgs.

if (Array.length ha) <> 6 then failwith "malformed hint" else
Some {
if (Array.length ha) <> 6 && (Array.length ha) <> 7
then failwith "malformed hint"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we raise an error instead?

Copy link
Author

Choose a reason for hiding this comment

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

That's what the old implementation did... what kind of error would you prefer?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure. Either it's OK to continue without the hint, in which case we could simply issue a warning and go on; or we want to fail, but in that case it'd be nice to include the file name of the hint file.

I noticed this while reading through, but indeed I wasn't criticizing a new addition :)

| `List strings ->
Some (List.map (function
| `String s -> s
| _ -> raise Exit
Copy link
Contributor

Choose a reason for hiding this comment

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

One problem with using Exceptions for control flow like this is that it yields very slow Javascript when we extract. But I think this code doesn't get run a lot, right?

Copy link
Author

Choose a reason for hiding this comment

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

Yep, that runs once while reading the hints file.

z3status
* int
* z3statistics
* option<string> // query hash
Copy link
Contributor

Choose a reason for hiding this comment

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

Past two/three fields, I tend to like records better (though I agree that adding the extra type is already a plus)

Copy link
Author

Choose a reason for hiding this comment

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

I have no opinion about that, happy to change it to records if that's preferred.

@@ -498,29 +504,67 @@ let refresh () =
bg_scope := List.flatten (List.rev !fresh_scope)

let mk_input theory =
let query_hash =
if Options.record_hints() || (Options.use_hints() && Options.use_hint_hashes()) then (
let ft = (fun x -> match x with
Copy link
Contributor

Choose a reason for hiding this comment

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

This could just be function instead of fun x -> match x with

@cpitclaudel
Copy link
Contributor

We have this bit in the interactive mode:

  if FStar.Options.record_hints() || FStar.Options.use_hints() then
    FStar.SMTEncoding.Solver.with_hints_db (List.hd (Options.file_list ()))
      (fun () -> go init_st)
  else
    go init_st

Does it need to be updated?

@s-zanella
Copy link
Contributor

I second Clement's excitement about this feature. If this could be made to work well in interactive, it would be a big productivity boost. But F* generates fresh identifiers on the fly, so as for now a query issued a second time will differ syntactically (mostly alpha-renaming, I believe) from the first time it was ran.

@cpitclaudel
Copy link
Contributor

But F* generates fresh identifiers on the fly, so as for now a query issued a second time will differ syntactically (mostly alpha-renaming, I believe) from the first time it was ran.

Good point. I don't expect this would be so hard to fix, though — probably just an issue of rolling back the gensyms when we step back in the interactive mode

@wintersteiger
Copy link
Author

@cpitclaudel: I think that part should be fine, we still need to load the hints, regardless of whether we use or ignore the hashes.

@s-zanella: Absolutely! There are some issues to think about, e.g. variable renaming, ordering, incrementality, etc, but I'm sure we can come up with something that's useful in interactive mode as well.

@wintersteiger
Copy link
Author

Just pushed a few improvements. This version takes less memory (smt2-string only generated once), but it's still not quite as fast as I'd like it to be. Ideas for optimizations are most welcome!

@cpitclaudel
Copy link
Contributor

Can you rebase and move the snapshot to the end? Or is there a way on github to exclude a snapshot that's in the middle of the history?

@wintersteiger
Copy link
Author

I don't think so, that would break the history. I can force-push after I hack the history locally, but I wouldn't want to do that after comments have been added (I think they would just disappear). The changes in fd15e83 are very small and local though.

@nikswamy
Copy link
Collaborator

Regarding this question from @cpitclaudel

We have this bit in the interactive mode:

  if FStar.Options.record_hints() || FStar.Options.use_hints() then
    FStar.SMTEncoding.Solver.with_hints_db (List.hd (Options.file_list ()))
      (fun () -> go init_st)
  else
    go init_st

Does it need to be updated?

I don't think so. The new feature is only enabled under FStar.Options.use_hints() && FStar.Options.use_hint_hashes(). So, this code should be ok as is.

@wintersteiger
Copy link
Author

@nikswamy thanks for adding comments, I totally neglected that part of the job!

@nikswamy nikswamy merged commit 50ff9be into master Sep 29, 2017
@catalin-hritcu catalin-hritcu deleted the cwinter_query_hashes branch April 7, 2018 14:26
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.

4 participants