Effizient ein großes Array mit Methodenhandeln bauenJava

Java-Forum
Anonymous
 Effizient ein großes Array mit Methodenhandeln bauen

Post by Anonymous »

Ich muss einen MethodHandle mit Signature (Internalcontext)-> Objekt [] Aus einer Liste mit der Signatur (Internalcontext)-> Objekt .

Code: Select all

  static MethodHandle makeArrayUsingCollector(List elements) {
// (Object[]) -> Object[]
var handle = MethodHandles.identity(Object[].class);
// (Object,Object...Object) -> Object[]
handle = handle.asCollector(Object[].class, elements.size());
// (InternalContext,InternalContext..InternalContext) -> Object[]
handle = MethodHandles.filterArguments(handle, 0, elements.toArray(new MethodHandle[0]));
// (InternalContext) -> Object[]
handle = MethodHandles.permuteArguments(
handle, methodType(Object[].class, InternalContext.class), new int[elements.size()]);
return handle;
}
Wenn die Liste jedoch größer ist, fehl

Code: Select all

  private static final int MAX_ARITY = 255;

static MethodHandle buildLargeArrayNaive(List elementFactories) {
if (elementFactories.size() < MAX_ARITY) {
return makeArrayUsingCollector(elementFactories);
}
var setter = MethodHandles.arrayElementSetter(Object[].class);
// (Object[], InternalContext) -> void
MethodHandle handle = null;
for (int i = 0; i < elementFactories.size(); i++) {
// (Object[], InternalContext) -> void
var setElement =
MethodHandles.filterArguments(
MethodHandles.insertArguments(setter, 1, i), 1, elementFactories.get(i));
if (handle == null) {
handle = setElement;
} else {
handle = MethodHandles.foldArguments(setElement, handle);
}
}

// (Object[], InternalContext) -> Object[]
handle =
MethodHandles.foldArguments(
MethodHandles.dropArguments(
MethodHandles.identity(Object[].class), 1, InternalContext.class),
handle);
return MethodHandles.foldArguments(
handle,
MethodHandles.insertArguments(
MethodHandles.arrayConstructor(Object[].class), 0, elementFactories.size()));
}
, das im Grunde genommen ein Array explizit konstruiert und dann jedes Element mit ordargumenten kombiniert
Dies funktioniert, aber der resultierende MethodeHandle erzeugt StackoverFlowerror Bei der Erstellung großer Arrays (sayer 100K -Elemente). Aus den Dokumenten auf Ordnungen ist dies sinnvoll, da jeder Aufruf eine Struktur des Schwanzaufrufs einstellt.

Code: Select all

static makeArray(InternalContext ctx) {
var a = new Object[
Ich habe festgestellt, dass ich dies mit Rekursion lösen kann < /p>
 static MethodHandle buildLargeArrayRecursive(List elementFactories) {
// (Object[], InternalContext) -> void
var handle = doBuildLargeArrayRecursive(0, elementFactories);
// (Object[], InternalContext) -> Object[]
handle =
MethodHandles.foldArguments(
MethodHandles.dropArguments(
MethodHandles.identity(Object[].class), 1, InternalContext.class),
handle);
;
return MethodHandles.foldArguments(
handle,
MethodHandles.insertArguments(
MethodHandles.arrayConstructor(Object[].class), 0, elementFactories.size()));
}

static final MethodHandle ARRAY_SETTER = MethodHandles.arrayElementSetter(Object[].class);

static MethodHandle doBuildLargeArrayRecursive(int offset, List elementFactories) {
int size = elementFactories.size();
if (size == 0) {
return MethodHandles.empty(methodType(void.class, Object[].class, InternalContext.class));
}
if (size == 1) {
return MethodHandles.filterArguments(
MethodHandles.insertArguments(ARRAY_SETTER, 1, offset), 1, elementFactories.get(0));
}
int half = size / 2;
var left = elementFactories.subList(0, half);
var right = elementFactories.subList(half, size);
return MethodHandles.foldArguments(
doBuildLargeArrayRecursive(offset + half, right), doBuildLargeArrayRecursive(offset, left));
}
< /code>
, was auf mindestens 100.000 Elemente zu skalieren scheint.  Aber dies ist eindeutig, dass dies O (logn) Stapelraum verbraucht.  Das ist wahrscheinlich in Ordnung, aber dies sind auch viele Methodenaufrufe ... < /p>
Ein paar Dinge sind aufgetreten, während ich darauf starrte: < /p>

  Sollte ich Helfer-Bulk-Set-Methoden erstellen, um mehr Basisfälle zu behandeln?  z.B. static void set4 (Objekt [], int offset, Objekt O1 ... Objekt O3) {...} 
könnte dazu beitragen, die Rekursion zu verringern? Oder sollte ich mich nur auf die VM verlassen, um dies durch das Inline -Inline zu tun? /> Wäre es besser, kleine Arrays zu konstruieren und sie mit System zusammenzusetzen.>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post