Computationally-heavy Processing in Plugins

Hello! I’m writing a plugin that needs to do some computationally-heavy or otherwise time-intensive processing behind a UI implemented in vanilla. I have two bottlenecks right now:

  1. I need to run updates on large portions (all Uppercase to Uppercase pairs, for example) of the Glyphs.font.kerning dictionary fairly regularly. Iterating across all these pairs takes a prohibitively long time – especially if the UI is blocked during these updates and I can’t show a progress indicator.

  2. I need to make a small-to-medium number of network requests from inside the plugin (say no more than 50), and the network latency waiting for my server to complete its processing and respond is also a bottleneck – again, especially if the UI is blocked and I can’t show a progress indicator.

With those constraints in mind, I have two questions that I’d like advice on:

  1. I’m wondering what my options are for parallelizing kerning table updates and network requests are in Glyphs + pyobjc + python 2.7. I’ve tried working with the multiprocessing module, but I can’t share the kerning table across multiple processes, so updates are still constrained to Glyphs process. How do batch updates to kerning work in the core application?

  2. I’m wondering how to display an updating progress bar during a sequence of network requests, or a set of updates to the kerning table. I’ve tried simply setting the vanilla ProgressBar object during iteration, but the UI never updates. I think this is because control is never released to the UI thread during the work of iteration.

Does anyone have any advice for me in parallizing heavy workloads and display progress during work? I’d really appreciate it!

If you want to do that in Python, you will have to reduce the ‘fairly regularly’, or let the user trigger it somehow. Besides, all possible combos can be a lot. So, in a fairly big font, it will always be too much to recalculate.

Thanks for the response! Definitely, the number of possible combos (even if you restrict to a single master and only a single pair from each kerning class) is a large number, on order thousands.

It definitely makes sense to allow the user to trigger such an intensive operation.

I’m wondering if it’s possible to display progress (per my question #2 above) through the kerning table once the user has triggered the recalculation. I’ve been having trouble getting the vanilla progress bar to update during the iteration across the kerning table, possibly because of the UI thread hypothesis I mentioned before.

I’m also wondering how Glyphs handles batch updating kerning (say when you copy and paste kerning values in as strings)?

Thanks again!

Normally this is done to put the processing in a background thread and when it is finishes, it calls into the main thread and the update to the data is done there. There are a couple of ways to do that in python but Google should be helpful with that.

Thanks, both. I’ve figured out how to stop my intensive operations from blocking the main thread. I’m still having trouble getting the progress bar to update consistently, but I’ll look into this on my own.

The progress bar is updated from the main thread. So if the main thread is blocked, it is blocked, too. And make sure to only update it from the main thread.