Spliterator fin paralelo especie

ChrLipp:

Me estoy poniendo en práctica un spliterator paginado (en Java) que debería permitir el acceso paralelo.

Tengo el siguiente caso de prueba (prueba está en Groovy con Spock):

def 'parallel, two pages'()
{
    when: 'a sorted range from 0 to 6'
    def fetcher = new IntegerRangePageFetcher(6)

    and: 'a spliterator with a page size of 5'
    def spliterator = new PagedSpliterator(fetcher, 5)

    and: 'a stream with the given range is collected to a list'
    def result = StreamSupport
            .stream(spliterator, true)
            .collect(Collectors.toList())

    then: 'the sort order is obeyed'
    expect result, contains(0, 1, 2, 3, 4, 5)
}

Este caso de prueba falla con el siguiente error:

Condition not satisfied:

expect result, contains(0, 1, 2, 3, 4, 5)
|      |
false  [5, 0, 1, 2, 3, 4]

Expected: iterable containing [<0>, <1>, <2>, <3>, <4>, <5>]
     but: item 0: was <5>

El spliterator tiene la characteristics()

return IMMUTABLE | ORDERED | SIZED | SUBSIZED | NONNULL;

El código funciona cuando no uso paralelo. Así que no entiendo ORDERED:

  • Si se establece, en caso de la garantía marco flujo de la orden y debe ordenar los resultados generados al utilizar trozos paralelos? Si es así, ¿por qué no lo hace una especie que en mi caso?
  • ¿O tengo un error en mi trySplitaplicación y tienen que dividir siguiendo un orden determinado? (actualmente divido en la mitad de las páginas abiertas, estancias 0-mediados del spliterator actual, de gama media va en el spliterator de nueva creación)
  • O debería llamar sort()antes collect()porque el marco no garantiza ningún orden en absoluto?

--- Actualización basada en la retroalimentación ---

Gracias por sus respuestas, que tienen dos errores lógicos en mi código. En primer lugar los fragmentos solicitados:

@Override
public Spliterator<T> trySplit()
{
    // first query
    if (pageIterator == null) {
        pageIterator = pageFetcher.fetchNextPage(paginationInfo);
    }

    // delegate split decision
    var newPaginationInfo = paginationInfo.split();
    if (newPaginationInfo == null) {
        log.info("* Spliterator returns null");
        return null;
    }

    // now we split
    var newSpliterator = new PagedSpliterator<>(pageFetcher, newPaginationInfo);
    return newSpliterator;
}

public PaginationInfo split()
{
    // when open range or nothing left we don't split
    if ((endElementIndex == -1) || !hasNextPage()) {
        return null;
    }

    // calculate the splitting position
    var firstHalfPages = (getEndPageIndex() - getNextPageIndex()) / 2;
    var midElementIndex = (getNextPageIndex() + firstHalfPages) * pageSize;

    // create an additional PaginationInfo and set the ranges according to the split position
    var newPaginationInfo = new PaginationInfo(this);
    newPaginationInfo.firstElementOnNextPageIndex = midElementIndex;
    newPaginationInfo.nextElementIndex = midElementIndex;

    endElementIndex = midElementIndex;

    return newPaginationInfo;
}

Primer error:

la Spliterator recién creado se establece en el segundo intervalo de medio en lugar de la primera. Leí sobre el prefijo en la documentación, pero se siente muy torpe para mí. Puedo dividir al tamaño de la página para tener múltiples peticiones paralelas. Al principio (primera instancia spliterator) Tengo que buscar a la primera página para obtener el contador de páginas y el elemento. Así que para solucionar el problema de orden tengo que ApUNTE los datos captados desde la primera a la segunda spliterator spliterator a obedecer la orden, esto se siente muy extraño y no es intuitivo para mí.

Segundo error:

    // first query
    if (pageIterator == null) {
        pageIterator = pageFetcher.fetchNextPage(paginationInfo);
    }

Todos spliterators creados subsecuentes recibirán una estimateSize()y una trySplit()llamada desde el marco. Durante esta situación requiere en este momento voy a buscar una página, pero esto bloquearían el paralelismo, la zona de alcance debe ocurrir más tarde en la tryAdvance()llamada.

Voy a poner en práctica estos cambios y luego volver a ti.

Louis Wasserman:

Sí, usted tiene un error en su trySplit. La documentación para Spliterator.trySplit especifica que el spliterator devuelto debe contener un prefijo de los elementos, si usted tiene la característica ORDENADO. Cambiar todo el Spliterator devuelto y el resto del contenido de la división.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=239563&siteId=1
Recomendado
Clasificación