[isabelle-dev] Remaining uses of Proof General?

Thomas Sewell thomas.sewell at nicta.com.au
Mon May 5 07:17:09 CEST 2014

On 03/05/14 00:05, Makarius wrote:
> On Tue, 29 Apr 2014, Thomas Sewell wrote:
>> I tried an adjustment a while ago in which I had the goal state print 
>> incrementally. Even if some of the subgoals took a while to print, 
>> you'd see the line with "goal (12 subgoals)" immediately, and then 
>> the subgoals as they were formatted. The short summary is that this 
>> helped a little sometimes, but I often still saw an empty Output 
>> panel for seconds after moving the cursor to a line that the 
>> continuous checker had already processed.
>> I strongly suspect that the print request was waiting in a queue 
>> somewhere. The system would become responsive again once it finished 
>> doing something else.
> That is the normal future task farm, with its restricted worker thread 
> pool.  All PIDE execution works via some Future.fork, with different 
> priorities in the queue.  Proof tasks have low priority, print tasks 
> have high priority. Once a task is running on some thread, it 
> continues and cannot be preempted by newer tasks with higher priority.
> The basic assumption is that each proof task does not run too long, 
> and if it does it is something to be improved in the application to 
> make it more smooth.  In contrast, Proof General makes it more easy to 
> produce huge and heavy proof scripts that can be hardly handled by 
> anyone else later.

Right. That seems to be the assumption that's being violated in the few 
cases where people are still keen on ProofGeneral, for instance, in 
Andreas' big complicated tactic applications.

The case where I get into trouble is in implementing a package-lite. I 
put together a collection of tactics or computations in ML blocks and 
execute them at some point in a theory via setup or ML. It's a bit like 
setting up a proper package and invoking it, but without the implied 
robustness or generality. Some of these can run for a minute or longer. 
They're the kind of computations that users might want to control.

With regard to the future task farm: This is pretty much what I'd 
expected. So we see a delay if all the available threads are executing 
tasks that take a while and are not the current print task. Adding more 
threads reduces the chance of this happening, but not much. The higher 
priority for print tasks means the delay will end as soon as any thread 
becomes available, so the more threads the faster on average that will 
happen, but without guarantees.

Let me make a proposal. I think that various users would appreciate it 
if one of the worker threads was reserved for print jobs caused by 
moving the cursor (highest priority tasks) and their dependencies 
(assuming more than one worker thread). That would hopefully make it 
easier to control the delay. If the user is cautious with moving the 
cursor and if enough proof dependencies have been processed, the system 
*should* be as responsive as PG. The delay would also be mostly 
unaffected by the proof task runtime, only the print task runtimes, 
which might be easier for an advanced user to manage.

Users running on batteries might also want a mode that restricts all 
threads to the behaviour above.

As always, I have no idea how difficult that would be.

>> On incremental printing: it's easy to implement by generalising a 
>> couple of the relevant Pretty operations to produce a Seq.seq 
>> internally rather than a list.
> That would probably violate some implicit assumptions about print 
> modes, which are a slightly odd intrusion into the purity of Pretty.T.
> What was the reason for incremental printing anyway?  Just performance 
> for huge goal states?  There are other bottle-necks concerning that, 
> and if goals really do get that big one should think about other ways 
> to expose them, not by "printing" in the old-fashioned way.
> Incrementality might have other reasons and actual benefits.  In the 
> early years of PIDE I had more ambitions for that, but it caused so 
> many additional problems in the document model and the GUI that I 
> removed most of it for the sake of delivering something that is 
> sufficiently stable to be usable in practice.

The reason for the experiment was that I was fixing some proofs 
somewhere, I forget where, which had relatively fast tactics executing 
on large, slow-to-print goals. I was probably in a context where Simpl 
was loaded, where printing is slower than usual (probably the 
print/parse translations, I've had a look and got nowhere.)

It occurred to me that I could debug some of my mistakes faster if I 
just knew whether or not the tactic I'd typed had solved a goal, and 
many more if I just saw the first goal. But the time saved is probably 
lost again adjusting the goals limit, and it's annoying to do by hand. 
Incremental output seemed like a good idea.

>> It looked promising initially, but then became really annoying, 
>> because Isabelle/jEdit or PIDE resets the Output buffer each time it 
>> gets more to display. So if you scroll down to look for something, 
>> you get scrolled back up for each time a subgoal prints, which can 
>> give the sensation that the editor is fighting you.
> There is a deeper conceptual problem here.  Several independent 
> entities want to update content of some GUI component: output window, 
> tree view etc.  This requires a "merge" of these change of the GUI 
> state, but that is usually only done by a hard reset on one side, 
> ignoring the other side. You can see that in jEdit's SideKick tree 
> view, Isabelle/jEdit's Output dockable with scrollbar and folds, or 
> even just in a plain Terminal with the scrollbar.

Sure. I was surprised that I got the incremental output working at all 
without any Scala changes.
I wasn't for a moment implying there wasn't a good reason for this 
behaviour or that doing this properly wouldn't be real work.

In a no-particular-urgency sense, better support for incremental output 
might be a good idea. As I said above, the delay length seen by the user 
is affected by the longest task times, including printing. If 
Isabelle/jEdit requested printed goals one at a time, that would 
probably decrease the longest task time quite a bit, especially the 
longest high-priority task time. I guess I had envisaged the sort of 
thing that facebook and slashdot do, where there's a "(10 more stories)" 
marker at the bottom of the news feed which prompts the fetching of more 
content as soon as it appears visually. I have no idea if that's 
workable in jEdit or not.

The other argument for better support for incremental output is in 
implementing the kind of package-lite I mentioned before. Like Andreas, 
I tend to debug these by tracing a lot of data, and searching in the 
output for suspect events. It's a little annoying that Isabelle/jEdit 
doesn't like having its output panel searched, and keeps resetting the 
cursor if there's a constant stream of data being printed.

I guess I could work around all of this myself, by inventing a language 
of commands that create a Future-forked stream of trace output, and some 
search functions for it. Maybe I should just do that.


More information about the isabelle-dev mailing list