Java s'exécutant sur AWS Lambda est lent la première fois, mais j'ai cherché un moyen de le rendre plus rapide. Je suis arrivé au contenu du site de référence à la fin et je l'ai essayé, donc c'est un record.
Les informations de latence ont été acquises par X-Ray.
Mettez simplement le fichier dans 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"));
Tout d'abord, essayez-le normalement.
<détails> <résumé> source entière </ résumé>
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;
}
}
Nombre de fois | Latence(ms) | Traitement du contenu |
---|---|---|
1 | 6200 | |
2 | 422 | |
3 | 217 | |
4 | 210 | |
5 | 315 |
Seule la première fois est en retard, le soi-disant démarrage à froid est en retard. Créer simplement un fichier dans S3 prend 6 secondes, n'est-ce pas?
Alors, que diriez-vous d'utiliser la "Concurrence fournie" qui est apparue à la fin de l'année dernière? https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/
Le code source est le même que celui de la vérification 1.
Nombre de fois | Latence(ms) | Traitement du contenu |
---|---|---|
1 | 5500 | |
2 | 266 | |
3 | 274 | |
4 | 402 | |
5 | 304 |
** La première fois n'est-elle pas encore en retard? .. ** ** Il en coûte 14,42 $ par mois juste pour provisionner la concurrence 1, mais ce n'est pas tellement. .. ..
Donc, après cela, désactivez la concurrence allouée et continuez la vérification
Afin de découvrir la cause de la lenteur à la première fois, j'ai essayé de séparer le traitement au premier démarrage de Lambda et au deuxième démarrage.
Créez une variable statique count
et essayez de ne renvoyer rapidement que le premier appel.
if (count == 1) {
count++;
return null;
}
<détails> <résumé> source entière </ résumé>
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;
}
}
Nombre de fois | Latence | Traitement du contenu |
---|---|---|
1 | 625ms | Processus d'initialisation uniquement |
2 | 5600ms | S3 PUT (1ère fois) |
3 | 393ms | S3 PUT (2ème fois) |
4 | 401ms | S3 PUT (3e fois) |
5 | 311ms | S3 PUT (4ème fois) |
Il s'avère que le processus d'initialisation n'est pas lent. Il semble que S3 PUT (première fois) prend beaucoup de temps.
Rendons la partie qui crée S3Client statique.
private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
<détails> <résumé> source entière </ résumé>
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;
}
}
Nombre de fois | Latence | Traitement du contenu |
---|---|---|
1 | 2400ms | Processus d'initialisation et création d'instance S3Client |
2 | 2200ms | S3 PUT (1ère fois) |
3 | 43ms | S3 PUT (2ème fois) |
4 | 46ms | S3 PUT (3e fois) |
5 | 78ms | S3 PUT (4ème fois) |
Oh! Il a fallu un peu plus de temps pour traiter la première fois, et la deuxième fois était un peu plus rapide. Cela s'accélère après la troisième fois, mais cela a-t-il également un effet?
J'ai trouvé que le traitement avec statique le rend plus rapide. Créons une fois un fichier factice avec l'initialiseur statique.
static{
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
}
<détails> <résumé> source entière </ résumé>
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;
}
}
Nombre de fois | Latence | Traitement du contenu |
---|---|---|
1 | 4000ms | Fichier factice S3 PUT (première fois) par traitement d'initialisation et méthode statique |
2 | 42ms | S3 PUT (2ème fois) |
3 | 125ms | S3 PUT (3e fois) |
4 | 42ms | S3 PUT (4ème fois) |
5 | 44ms | S3 PUT (5ème fois) |
Félicitations, la deuxième fois et les suivantes sont devenues plus rapides!
Puisqu'il est devenu plus rapide dans la vérification 5, sera-t-il plus rapide dès la première fois s'il est combiné avec la simultanéité provisionnée? !!
La source est la même que la vérification 5.
Nombre de fois | Latence | Traitement du contenu |
---|---|---|
1 | 80ms | Processus d'initialisation |
2 | 370ms | S3 PUT (2ème fois) * Parce qu'il a déjà été exécuté une fois avec l'initialiseur statique pendant Provisioned |
3 | 43ms | S3 PUT (3e fois) |
4 | 72ms | S3 PUT (4ème fois) |
5 | 84ms | S3 PUT (5ème fois) |
** Je l'ai fait! ** ** C'est ce à quoi je m'attendais.
La forme finale est comme ça.
<détails> <résumé> source entière </ résumé>
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;
}
}
Nombre de fois | Latence | Traitement du contenu |
---|---|---|
1 | 552ms | S3 PUT (2ème fois) * Parce qu'il a déjà été exécuté une fois avec l'initialiseur statique pendant Provisioned |
2 | 118ms | S3 PUT (3e fois) |
3 | 44ms | S3 PUT (4ème fois) |
4 | 86ms | S3 PUT (5ème fois) |
5 | 146ms | S3 PUT (6ème fois) |
Félicitations, félicitations.
Apparemment, le chargeur de classe Java charge la classe lorsque la classe est appelée pour la première fois, et il semble que le chargement initial de la classe prend du temps. Donc, il semble que si vous le chargez une fois et chargez la classe, ce sera plus rapide à partir de la prochaine fois.
Ce serait bien si toutes les classes étaient chargées en premier, pas quand elles ont été appelées, mais n'est-ce pas possible?
Le site de référence est ici.
Blog de la méthode de classe https://dev.classmethod.jp/articles/report-best-practive-for-java-on-lambda/
Matériel de session à 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
Autres blogs que j'ai trouvés https://pattern-match.com/blog/2020/03/14/springboot2-and-aws-lambda-provisioned-concurrency/
Recommended Posts