If self._maximum_samples_per_batch is specified, then split the batch
        into smaller sub-batches if it exceeds the maximum size.

        Parameters
        ----------
        batch_instances : ``Iterable[Instance]``
            A candidate batch.
        excess : ``Deque[Instance]``
            Instances that were not sufficient to form an entire batch
            previously. They will be used as part of the first sub-batch. This
            will be populated with instances from the end of batch_instances
            that do not consist of more than self._maximum_samples_per_batch
            samples or self._batch_size instances. It is the caller's
            responsibility to place these in a batch too, which may, of course,
            be done in part with subsequent calls to this method.

            WARNING: Mutated in place!

def _ensure_batch_is_sufficiently_small(
            self,
            batch_instances: Iterable[Instance],
            excess: Deque[Instance]) -> List[List[Instance]]:
        """
        If self._maximum_samples_per_batch is specified, then split the batch
        into smaller sub-batches if it exceeds the maximum size.

        Parameters
        ----------
        batch_instances : ``Iterable[Instance]``
            A candidate batch.
        excess : ``Deque[Instance]``
            Instances that were not sufficient to form an entire batch
            previously. They will be used as part of the first sub-batch. This
            will be populated with instances from the end of batch_instances
            that do not consist of more than self._maximum_samples_per_batch
            samples or self._batch_size instances. It is the caller's
            responsibility to place these in a batch too, which may, of course,
            be done in part with subsequent calls to this method.

            WARNING: Mutated in place!
        """
        if self._maximum_samples_per_batch is None:
            assert not excess
            return [list(batch_instances)]

        key, limit = self._maximum_samples_per_batch

        batches: List[List[Instance]] = []
        batch: List[Instance] = []
        padding_length = -1

        excess.extend(batch_instances)
        while excess:
            instance = excess.popleft()

            if self.vocab is not None:
                # we index here to ensure that shape information is available,
                # as in some cases (with self._maximum_samples_per_batch)
                # we need access to shaping information before batches are constructed)
                instance.index_fields(self.vocab)
            field_lengths = instance.get_padding_lengths()
            for _, lengths in field_lengths.items():
                try:
                    padding_length = max(padding_length,
                                         lengths[key])
                except KeyError:
                    pass

            proposed_batch_size = len(batch) + 1

            # Adding the current instance would exceed the batch size or sample size.
            if proposed_batch_size >= self._batch_size or padding_length * proposed_batch_size > limit:
                # Output the already existing batch
                batches.append(batch)

                # Put the current instance back, reset state.
                excess.appendleft(instance)
                batch = []
                padding_length = -1
            else:
                batch.append(instance)

        # Keep the current batch as excess.
        excess.extend(batch)

        return batches