### Summary

Executing a playbook with many hosts, there is massive overhead in checking whether the hosts list is a pattern, see for yourself on this callgrind graph:

![grafik](https://user-images.githubusercontent.com/3154871/111359016-4a4bf480-868b-11eb-8c8f-55b6a6a10bd7.png)

https://github.com/ansible/ansible/blob/da60525610a384bb04833b1c6429d9db6a87ef64/lib/ansible/vars/manager.py#L490

That check has quadratic runtime with the number of hosts - with a lot of hosts, commenting that check out reduces runtime manyfold.

### Issue Type

Bug Report

### Component Name

variable manager

### Ansible Version

2.10.5, devel

### OS / Environment

Ubuntu

### Steps to Reproduce

```yaml
- hosts: localhost
  tasks:
    - set_fact:
        extra_tasks: true # compute it
        hosts: "{{ [an, array, with, 5100, computed, hosts] }}"

- hosts: "{{ hostvars.localhost.hosts }}"
  vars:
    extra_tasks: "{{ hostvars.localhost.do_extra_tasks }}"
  tasks:
   # some more tasks here
    - name: Execute extra tasks
      command: /bin/true # example
      when: extra_tasks
```

### Expected Results

Execute in tens of seconds.

### Actual Results

Take over 5 minutes to execute.
'''
        Wait for the handler tasks to complete, using a short sleep
        between checks to ensure we don't spin lock
        '''
        ret_results = []
        handler_results = 0
        display.debug("waiting for handler results...")
        while (self._pending_handler_results > 0 and
               handler_results < len(notified_hosts) and
               not self._tqm._terminated):
            if self._tqm.has_dead_workers():
                raise AnsibleError("A worker was found in a dead state")
            results = self._process_pending_results(iterator, do_handlers=True)
            ret_results.extend(results)
            handler_results += len([
                r._host for r in results if r._host in notified_hosts and
                r.task_name == handler.name])
            if self._pending_handler_results > 0:
                time.sleep(C.DEFAULT_INTERNAL_POLL_INTERVAL)
        display.debug("no more pending handlers, returning what we have")
        return ret_results
    def _wait_on_pending_results(self, iterator):