Ist Java unter AWS Lambda langsam?

Java, das auf AWS Lambda ausgeführt wird, ist beim ersten Mal langsam, aber ich habe nach einer Möglichkeit gesucht, es schneller zu machen. Ich bin am Ende zum Inhalt der Referenzseite gekommen und habe es tatsächlich ausprobiert, es ist also eine Aufzeichnung.

Die Latenzinformationen wurden von X-Ray erfasst.

Testziel

Legen Sie die Datei einfach in S3

S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
PutObjectResponse result = s3.putObject(
        PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
        RequestBody.fromString("contents"));

Überprüfung 1 Normale Ausführung

Versuchen Sie es zuerst normal.

gesamte Quelle
package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

public class TestTarget0429 implements RequestHandler<Object, Object> {

    public Object handleRequest(final Object input, final Context context) {
        String ENV_BUCKET = System.getenv("BUCKET");

        S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);

        return null;
    }
}
Anzahl Latenz(ms) Inhalte verarbeiten
1 6200
2 422
3 217
4 210
5 315

Nur das erste Mal ist spät, der sogenannte Kaltstart ist spät. Nur eine Datei in S3 zu erstellen ist 6 Sekunden langsam, nicht wahr?

Überprüfung 2 Aktivieren Sie die bereitgestellte Parallelität

Wie wäre es also mit der "Provisioned Concurrency", die Ende letzten Jahres erschien? https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/

Der Quellcode ist der gleiche wie bei Verification 1.

Anzahl Latenz(ms) Inhalte verarbeiten
1 5500
2 266
3 274
4 402
5 304

** Ist das erste Mal nicht noch zu spät? .. ** ** ** Die Bereitstellung von Concurrency 1 kostet 14,42 USD pro Monat, ist aber nicht so viel. .. ..

Deaktivieren Sie anschließend Provisioned Concurrency und setzen Sie die Überprüfung fort

Überprüfung 3 Trennung der Verarbeitung (ohne bereitgestellte Parallelität)

Um die Ursache für die Langsamkeit beim ersten Mal herauszufinden, habe ich versucht, die Verarbeitung beim ersten Start von Lambda und beim zweiten Start zu trennen.

Erstellen Sie eine statische "count" -Variable und versuchen Sie es mit einer Eile, die nur den ersten Aufruf zurückgibt.

        if (count == 1) {
            count++;
            return null;
        }
gesamte Quelle
package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

public class TestTarget0429 implements RequestHandler<Object, Object> {

    private static int count = 1;

    public Object handleRequest(final Object input, final Context context) {
        if (count == 1) {
            count++;
            return null;
        }
        
        String ENV_BUCKET = System.getenv("BUCKET");

        S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);

        return null;
    }
}

Ergebnis

Anzahl Latenz Inhalte verarbeiten
1 625ms Nur Initialisierungsprozess
2 5600ms S3 PUT (1. Mal)
3 393ms S3 PUT (2. Mal)
4 401ms S3 PUT (3. Mal)
5 311ms S3 PUT (4. Mal)

Es stellt sich heraus, dass der Initialisierungsprozess nicht langsam ist. Es scheint, dass S3 PUT (zum ersten Mal) lange dauert.

Überprüfung 4 Machen Sie den Initialisierungsprozess statisch (keine bereitgestellte Parallelität).

Lassen Sie uns den Teil, der S3Client erstellt, statisch machen.

private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
gesamte Quelle
package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

public class TestTarget0429 implements RequestHandler<Object, Object> {

    private static int count = 1;

    private static String ENV_BUCKET = System.getenv("BUCKET");
    private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();

    public Object handleRequest(final Object input, final Context context) {
        if (count == 1) {
            count++;
            return null;
        }

        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);

        return null;
    }
}

Ergebnis

Anzahl Latenz Inhalte verarbeiten
1 2400ms Initialisierungsprozess und Erstellung der S3Client-Instanz
2 2200ms S3 PUT (1. Mal)
3 43ms S3 PUT (2. Mal)
4 46ms S3 PUT (3. Mal)
5 78ms S3 PUT (4. Mal)

Oh! Die erste Verarbeitung dauerte etwas länger und die zweite etwas schneller. Nach dem dritten Mal wird es schneller, aber hat das auch Auswirkungen?

Überprüfung 5 Führen Sie dies einmal mit dem statischen Initialisierer durch (ohne bereitgestellte Parallelität).

Ich fand, dass die Verarbeitung mit statischer Aufladung es schneller macht. Lassen Sie uns einmal eine Dummy-Datei mit dem statischen Initialisierer erstellen.

static{
    PutObjectResponse result = s3.putObject(
            PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
            RequestBody.fromString("contents"));

    System.out.println(result);
}
gesamte Quelle
package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

public class TestTarget0429 implements RequestHandler<Object, Object> {

    private static int count = 1;

    private static String ENV_BUCKET = System.getenv("BUCKET");
    private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();

    static{
        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);
    }

    public Object handleRequest(final Object input, final Context context) {
        if (count == 1) {
            count++;
            return null;
        }

        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);

        return null;
    }
}

Ergebnis

Anzahl Latenz Inhalte verarbeiten
1 4000ms S3 PUT-Dummy-Datei (zum ersten Mal) durch Initialisierungsverarbeitung und statische Methode
2 42ms S3 PUT (2. Mal)
3 125ms S3 PUT (3. Mal)
4 42ms S3 PUT (4. Mal)
5 44ms S3 PUT (5. Mal)

Herzlichen Glückwunsch, das zweite und die folgenden Male sind schneller geworden!

Überprüfung 6 Überprüfung 5 + Bereitgestellte Parallelität

Wird es vom ersten Mal an schneller sein, wenn es mit Provisioned Concurrency kombiniert wird, da es in Verifikation 5 schneller wurde? !!

Die Quelle ist dieselbe wie bei Überprüfung 5.

Anzahl Latenz Inhalte verarbeiten
1 80ms Initialisierungsprozess
2 370ms S3 PUT (2. Mal) * Da es während Provisioned bereits einmal mit dem statischen Initialisierer ausgeführt wurde
3 43ms S3 PUT (3. Mal)
4 72ms S3 PUT (4. Mal)
5 84ms S3 PUT (5. Mal)

** Ich habs gemacht! ** ** ** Das habe ich erwartet.

Endergebnis

Die endgültige Form ist wie folgt.

gesamte Quelle
package helloworld;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

public class TestTarget0429 implements RequestHandler<Object, Object> {

    private static String ENV_BUCKET = System.getenv("BUCKET");
    private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();

    static{
        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);
    }

    public Object handleRequest(final Object input, final Context context) {
        PutObjectResponse result = s3.putObject(
                PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
                RequestBody.fromString("contents"));

        System.out.println(result);

        return null;
    }
}
Anzahl Latenz Inhalte verarbeiten
1 552ms S3 PUT (2. Mal) * Da es während Provisioned bereits einmal mit dem statischen Initialisierer ausgeführt wurde
2 118ms S3 PUT (3. Mal)
3 44ms S3 PUT (4. Mal)
4 86ms S3 PUT (5. Mal)
5 146ms S3 PUT (6. Mal)

Glückwunsch Glückwunsch.

Erwägung

Anscheinend lädt der Java-Klassenlader die Klasse, wenn die Klasse zum ersten Mal aufgerufen wird, und es scheint, dass das anfängliche Laden der Klasse Zeit braucht. Wenn Sie es also einmal laden und die Klasse laden, wird es beim nächsten Mal schneller.

Es wäre schön, wenn alle Klassen zuerst geladen würden, nicht wenn sie aufgerufen würden, aber ist das nicht möglich?

Die Referenzseite ist hier.

Blog der Klassenmethode https://dev.classmethod.jp/articles/report-best-practive-for-java-on-lambda/

Sitzungsmaterial bei re: Invent 2019 https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Best_practices_for_AWS_Lambda_and_Java_SVS403-R1.pdf https://youtu.be/ddg1u5HLwg8

Andere Blogs habe ich gefunden https://pattern-match.com/blog/2020/03/14/springboot2-and-aws-lambda-provisioned-concurrency/

Recommended Posts

Ist Java unter AWS Lambda langsam?
Hallo Welt mit AWS Lambda + Java
Veröffentlichen Sie regelmäßig Bild-Tweets auf Twitter mit AWS Lambda + Java
Was ist ein Lambda-Ausdruck (Java)
Führen Sie C-Binärdateien auf AWS Lambda aus
AWS Lambda (Lambda) Teil 1 mit Java startet jetzt
Erstellen Sie eine Java 8-Entwicklungsumgebung mit AWS Cloud 9
Was ist java
Was ist Java <>?
Was ist java
Hallo Java Lambda
[Java] Lambda-Ausdruck
Java Lambda Ausdruck
Verwendung des Java-Frameworks mit AWS Lambda! ??
Installieren Sie Java auf dem Mac
So stellen Sie Java mit Serverless Framework für AWS Lambda bereit
AWS Lambda Zeitzonenänderung
Java Neutral Lambda Tabellenausdruck 1
Quarkus rettet Java Lambda! ??
Führen Sie PostgreSQL unter Java aus
Verstehen Sie Java 8 Lambda-Ausdrücke
Variationen von Java-Lambda-Ausdrücken
Was ist Java-Kapselung?
Sie können dies sofort mit Serverless Framework Serverless mit AWS tun (API + Lambda [Java] ist einfach einzurichten).
Java 8 Lambda-Ausdruck Feature
Java Lambda Ausdruck Memo
Über Java-Lambda-Ausdrücke
Was ist Java-Technologie?
Was ist Java API-Java?
Java Lambda Ausdruck [Notiz schreiben]
Erläutern Sie Java 8-Lambda-Ausdrücke
Java 8 studieren (Lambda-Ausdruck)
Überprüfen Sie java8 ~ Lambda Typ ~
Wieder Java-Lambda-Ausdruck
[Java] Was ist flatMap?
[Java] Was ist ArrayList?
Erstellen Sie einen SlackBot mit AWS Lambda & API Gateway in Java
So stellen Sie eine Kotlin (Java) -App auf AWS fargate bereit
Tipps rund um das Beispiel, um Lambda von Java auf CodePipeline freizugeben
[Java] Code, der schwer zu bemerken, aber furchtbar langsam ist
Java-Versionsverwaltung unter macOS
Verwenden Sie Lambda-Ebenen mit Java
Was ist Java Assertion? Zusammenfassung.
Installieren Sie OpenJDK7 (JAVA) unter Ubuntu 14.04
Downgrade von Java unter openSUSE Linux
Beim Übergeben von Java Gold SE 8
Oracle Java 8 unter Docker Ubuntu
Java8-Stream, Zusammenfassung des Lambda-Ausdrucks
Mit [AWS] CodeStar können Sie ein Spring (Java) -Projekt erstellen, das auf Lambda in nur 3 Minuten ausgeführt wird! !!
[Java] Einführung in den Lambda-Ausdruck
Installieren Sie Java unter WSL Ubuntu 18.04
Was ist eine Java-Sammlung?
[Windows] Java-Code ist verstümmelt
Was ist ein Lambda-Ausdruck?
Führen Sie das Java-Applet auf Ubuntu aus