`transition_processing_memory` optimizations, etc. (#4487)
`transition_processing_memory` optimizations, etc. (#4487)

* Use `.get` to retrieve alias

Avoids checking for the value and then retrieving it by simply trying to
get the associated value. If it is not found, it is `None`, which is
fast to check after and handle.

* Assign `WorkerState` object

Allows Cython to optimize operations on this object.

* Use `_address` attribute in `host`

This should allow faster access (particularly in Cython).

* Drop `bandwidth` intermediate variable

This is a holdover from before the `SchedulerState` refactor. Now this
is properly typed and can be used efficiently in Cython anyways.

* Drop `total_nthreads` intermediate variable

* Drop `total_occupancy` intermediate variable

* Drop `bandwidth` intermediate variable

* Annotate `s` as a `set`

* Drop extra `client_msgs` definitions

* Define `recommendations` up top

* Annotate variables involved in `startstops`

* Assign `compute_start` and `compute_stop` `0`

If we don't have `startstops`, just assign `compute_start` and
`compute_stop` `0` instead of `None`.

* Type `compute_start` & `compute_stop` as `double`

* Skip collecting unused startstop list, `L`

We only ever grab the first value from this `list`. The rest of the
values are ignored. So simply alter the loop to collect this first match
and skip collecting the rest of the `list`. Should speed this code up
considerably.

* Type durations as `double`

Should speed up computations using these.

* Type various durations

* Use temporary variables to group some work

* Type `set` iterated over

* Just check `_processing_on is not None`

We already know this is a `WorkerState` object or `None`. Also there is
not really a concept of a `False`y `WorkerState`. So the only way this
expression is `False` is if it is `None`. To speed up the check and
avoid unnecessary work. Just check that it `is not None`, which is a
fast pointer check.

* Swap `comm` & `old` order

* Relax `startstops` typing

Apparently this can be a `tuple` in some cases.

* Type `duration` as `double`

* Simplify branching in `_remove_from_processing`

* Fuse `for`-loops in `_client_releases_keys`

Instead of collecting `TaskState`s for special handling in another loop,
go ahead and handle them as they come up within the check where they
were previously collected. Avoids a second loop and build up another
collection for it.

* Use `.get` in `handle_missing_data`

Avoid checking for the key and then getting it. Instead just use `.get`
knowing it will return `None` if the key is not found. Then handle the
case where `None` is returned as the missing key case.

* Annotate variables in `release_worker_data`

Should allow the more efficient Python C APIs to be used.

* Use `.get` to grab stealing extension

* Assign `double` to variable

Avoids duplicate retrieval. Also handles the coercion to `double` once.

* Use `parent` to get stealing extension quickly

* Move `ClientState` annotation into `else`

* Use `dict` comprehension in `_task_to_client_msgs`

* Create client msgs from keys directly

Avoid collecting an intermediate list of client keys and instead use
them to produce messages directly.

* Annotate couple variables in attribute functions

* Type `duration` as `double` w/`-1` default

This makes it easier to type this value and thus for Cython to optimize
this value throughout.

* Tidy up `new_task`

* Annotate arguments in `new_task`

Should knock out type checking when the function is called, which should
simplify the work needed in later steps.

* Use `None` with `pop` to defer object creation

This allows us to only create the `set` `s` when we know we need it.
Otherwise we just get the `set` previously contained in the `dict`.

* Just check `s` is non-trivial

Instead of creating an empty `set` when `s` is not defined, just check
that `s` is non-trivial (either `None` or empty). This should be a bit
faster and avoid the unnecessary creation step.

* Make `_unknown_durations` an ordinary `dict`

As `defaultdict`s are difficult for Cython to optimize and usually a
`dict` will suffice, change `_unknown_duractions` to a `dict` to allow
Cython to use Python C API specific to `dict`s.

* Assign messages to `client_msgs` for clarity

* Annotate `for`-loops in `valid_workers` for perf

* Use `dict`s for `_host_info` & `_resources`

This makes it easier to annotate these more accurately and benefit from
Cython's optimizations around these `dict`-typed variables. Requires a
very small amount of checking for keys and setting their values if not
present. Though this remains efficient in both Python & Cython as well
as compact.

* Annotate `"addresses"` field as `set`

* Assign to `dw` after `sw` is filled

* Drop some unneeded intermediate variables

These are annotated local variables, which are holdovers from before the
`SchedulerState` refactor. We can now drop these and use
`SchedulerState` to access these directly.

* Use `wws` for a looping variable

* Assign `ws` `None` and `return`

* Assign `ws` result and `return`

* Join `if`s and cleanup spacing

* Get `len(candidates)` and branch based on that

Cython will turn this into a very efficient `switch...case` statement.
So this cuts down on the overhead of comparisons and checks (paying them
once when computing the length). Then focuses on just checking this C
typed integral value for which `case` to run.
dask/distributed,dask/distributed,dask/distributed,dask/distributed