-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29108 from patriot1burke/warmup-stage
Warmup stage
- Loading branch information
Showing
18 changed files
with
382 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
core/deployment/src/main/java/io/quarkus/deployment/CracConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package io.quarkus.deployment; | ||
|
||
import java.util.Optional; | ||
|
||
import io.quarkus.runtime.annotations.ConfigItem; | ||
import io.quarkus.runtime.annotations.ConfigPhase; | ||
import io.quarkus.runtime.annotations.ConfigRoot; | ||
|
||
@ConfigRoot(phase = ConfigPhase.BUILD_TIME) | ||
public class CracConfig { | ||
|
||
/** | ||
* Enable/Disable CRAC integration | ||
* <p> | ||
* Default value is dependent on extensions deployed | ||
* (i.e. when using AWS Lambda extensions, this will be set to true by default) | ||
*/ | ||
@ConfigItem | ||
Optional<Boolean> enable; | ||
|
||
/** | ||
* Will do a classpath search for all META-INF/quarkus-preload-classes.txt files | ||
* These files contain fully qualified classnames that should be loaded | ||
* in the CRAC`beforeCheckpoint()` phase | ||
*/ | ||
@ConfigItem(defaultValue = "true") | ||
boolean preloadClasses; | ||
|
||
/** | ||
* if preloading classes, specify whether or not | ||
* to do static initialization when preloading these classes. | ||
*/ | ||
@ConfigItem(defaultValue = "true") | ||
boolean initializeClasses; | ||
|
||
/** | ||
* Perform Application.start() within CRAC `beforeCheckpoint()` phase. | ||
*/ | ||
@ConfigItem(defaultValue = "true") | ||
boolean fullWarmup; | ||
|
||
/** | ||
* When CRAC is enabled, it generates the application class list so it can be preloaded. | ||
*/ | ||
@ConfigItem(defaultValue = "true") | ||
boolean generateApplicationClassList; | ||
|
||
} |
91 changes: 91 additions & 0 deletions
91
core/deployment/src/main/java/io/quarkus/deployment/CracProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package io.quarkus.deployment; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
|
||
import org.jboss.jandex.ClassInfo; | ||
import org.jboss.logging.Logger; | ||
|
||
import io.quarkus.deployment.annotations.BuildProducer; | ||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.annotations.ExecutionTime; | ||
import io.quarkus.deployment.annotations.Record; | ||
import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem; | ||
import io.quarkus.deployment.builditem.CracDefaultValueBuildItem; | ||
import io.quarkus.deployment.builditem.CracEnabledBuildItem; | ||
import io.quarkus.deployment.builditem.GeneratedClassBuildItem; | ||
import io.quarkus.deployment.builditem.PreloadClassBuildItem; | ||
import io.quarkus.deployment.builditem.PreloadClassesEnabledBuildItem; | ||
import io.quarkus.deployment.builditem.TransformedClassesBuildItem; | ||
import io.quarkus.deployment.pkg.steps.NativeBuild; | ||
import io.quarkus.runtime.CracRecorder; | ||
|
||
public class CracProcessor { | ||
|
||
private static Logger logger = Logger.getLogger(CracProcessor.class); | ||
|
||
@BuildStep(onlyIf = IsNormal.class, onlyIfNot = NativeBuild.class) | ||
@Record(ExecutionTime.STATIC_INIT) | ||
public void processCrac(BuildProducer<PreloadClassesEnabledBuildItem> preload, | ||
BuildProducer<CracEnabledBuildItem> cracEnabled, | ||
CracRecorder crac, | ||
CracConfig config, | ||
Optional<CracDefaultValueBuildItem> defaultVal) { | ||
if (config.enable.isPresent()) { | ||
if (!config.enable.get().booleanValue()) { | ||
return; | ||
} | ||
|
||
} else if (defaultVal == null || !defaultVal.isPresent() || !defaultVal.get().isDefaultValue()) { | ||
return; | ||
} | ||
cracEnabled.produce(CracEnabledBuildItem.INSTANCE); | ||
if (config.preloadClasses) | ||
preload.produce(new PreloadClassesEnabledBuildItem(config.initializeClasses)); | ||
crac.register(config.fullWarmup); | ||
} | ||
|
||
@BuildStep(onlyIf = IsNormal.class, onlyIfNot = NativeBuild.class) | ||
public void generateClassListFromApplication( | ||
CracConfig config, | ||
Optional<CracDefaultValueBuildItem> defaultVal, | ||
BuildProducer<PreloadClassBuildItem> producer, | ||
TransformedClassesBuildItem transformedClasses, | ||
ApplicationArchivesBuildItem applicationArchivesBuildItem, | ||
List<GeneratedClassBuildItem> generatedClasses) { | ||
if (config.enable.isPresent()) { | ||
if (!config.enable.get()) { | ||
return; | ||
} | ||
} else if (defaultVal == null || !defaultVal.isPresent() || !defaultVal.get().isDefaultValue()) { | ||
return; | ||
} | ||
|
||
if (config.generateApplicationClassList) { | ||
for (Set<TransformedClassesBuildItem.TransformedClass> transformedSet : transformedClasses | ||
.getTransformedClassesByJar().values()) { | ||
for (TransformedClassesBuildItem.TransformedClass transformed : transformedSet) { | ||
String className = transformed.getClassName(); | ||
if (className != null) { | ||
producer.produce(new PreloadClassBuildItem(className)); | ||
} | ||
} | ||
} | ||
|
||
for (GeneratedClassBuildItem i : generatedClasses) { | ||
if (i.isApplicationClass()) { | ||
if (i.getName() != null) { | ||
String cn = i.getName().replace("/", "."); | ||
producer.produce(new PreloadClassBuildItem(cn)); | ||
} | ||
} | ||
} | ||
|
||
for (ClassInfo clz : applicationArchivesBuildItem.getRootArchive().getIndex().getKnownClasses()) { | ||
producer.produce(new PreloadClassBuildItem(clz.toString())); | ||
} | ||
} | ||
} | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
core/deployment/src/main/java/io/quarkus/deployment/builditem/CracDefaultValueBuildItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package io.quarkus.deployment.builditem; | ||
|
||
import io.quarkus.builder.item.SimpleBuildItem; | ||
|
||
/** | ||
* Allows extensions to set default value for enabling CRAC | ||
*/ | ||
public final class CracDefaultValueBuildItem extends SimpleBuildItem { | ||
private final boolean defaultValue; | ||
|
||
public CracDefaultValueBuildItem(boolean defaultValue) { | ||
this.defaultValue = defaultValue; | ||
} | ||
|
||
public boolean isDefaultValue() { | ||
return defaultValue; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
core/deployment/src/main/java/io/quarkus/deployment/builditem/CracEnabledBuildItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package io.quarkus.deployment.builditem; | ||
|
||
import io.quarkus.builder.item.SimpleBuildItem; | ||
|
||
/** | ||
* Marker item to specify that CRAC is enabled | ||
*/ | ||
public final class CracEnabledBuildItem extends SimpleBuildItem { | ||
public static final CracEnabledBuildItem INSTANCE = new CracEnabledBuildItem(); | ||
|
||
private CracEnabledBuildItem() { | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
core/deployment/src/main/java/io/quarkus/deployment/builditem/PreloadClassBuildItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.quarkus.deployment.builditem; | ||
|
||
import io.quarkus.builder.item.MultiBuildItem; | ||
import io.smallrye.common.constraint.Assert; | ||
|
||
/** | ||
* Class to be preloaded in static initialization phase of Quarkus | ||
*/ | ||
public final class PreloadClassBuildItem extends MultiBuildItem { | ||
private final String className; | ||
|
||
/** | ||
* Construct a new instance. | ||
* | ||
* @param className the class name (must not be {@code null}) | ||
*/ | ||
public PreloadClassBuildItem(final String className) { | ||
this.className = Assert.checkNotNullParam("className", className); | ||
} | ||
|
||
/** | ||
* Get the class name. | ||
* | ||
* @return the class name (not {@code null}) | ||
*/ | ||
public String getClassName() { | ||
return className; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...loyment/src/main/java/io/quarkus/deployment/builditem/PreloadClassesEnabledBuildItem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package io.quarkus.deployment.builditem; | ||
|
||
import io.quarkus.builder.item.SimpleBuildItem; | ||
|
||
/** | ||
* Extension build steps can produce this if preloading classes is enabled | ||
*/ | ||
public final class PreloadClassesEnabledBuildItem extends SimpleBuildItem { | ||
private final boolean initialize; | ||
|
||
public PreloadClassesEnabledBuildItem(boolean initialize) { | ||
this.initialize = initialize; | ||
} | ||
|
||
public boolean doInitialize() { | ||
return initialize; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
core/deployment/src/main/java/io/quarkus/deployment/steps/PreloadClassesBuildStep.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.quarkus.deployment.steps; | ||
|
||
import static io.quarkus.runtime.PreloadClassesRecorder.QUARKUS_GENERATED_PRELOAD_CLASSES_FILE; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.stream.Collectors; | ||
|
||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.annotations.ExecutionTime; | ||
import io.quarkus.deployment.annotations.Record; | ||
import io.quarkus.deployment.builditem.GeneratedResourceBuildItem; | ||
import io.quarkus.deployment.builditem.PreloadClassBuildItem; | ||
import io.quarkus.deployment.builditem.PreloadClassesEnabledBuildItem; | ||
import io.quarkus.runtime.PreloadClassesRecorder; | ||
|
||
public class PreloadClassesBuildStep { | ||
@BuildStep | ||
@Record(ExecutionTime.STATIC_INIT) | ||
public void preInit(Optional<PreloadClassesEnabledBuildItem> preload, PreloadClassesRecorder recorder) { | ||
if (!preload.isPresent()) | ||
return; | ||
recorder.invokePreloadClasses(preload.get().doInitialize()); | ||
} | ||
|
||
@BuildStep | ||
public GeneratedResourceBuildItem registerPreInitClasses(List<PreloadClassBuildItem> items) { | ||
if (items == null || items.isEmpty()) | ||
return null; | ||
// ensure unique & sorted | ||
final String names = items.stream().map(PreloadClassBuildItem::getClassName).sorted().distinct() | ||
.map(s -> s.concat(System.lineSeparator())).collect(Collectors.joining()); | ||
return new GeneratedResourceBuildItem("META-INF/" + QUARKUS_GENERATED_PRELOAD_CLASSES_FILE, | ||
names.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
core/runtime/src/main/java/io/quarkus/runtime/CracRecorder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package io.quarkus.runtime; | ||
|
||
import io.quarkus.runtime.annotations.Recorder; | ||
|
||
/** | ||
* Registers a CRAC resource. Must be called in static initialization phase! | ||
*/ | ||
@Recorder | ||
public class CracRecorder { | ||
|
||
public static boolean enabled = false; | ||
public static boolean fullWarmup = false; | ||
|
||
public void register(boolean fw) { | ||
enabled = true; | ||
fullWarmup = fw; | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
core/runtime/src/main/java/io/quarkus/runtime/PreloadClassesRecorder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package io.quarkus.runtime; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.net.URL; | ||
import java.net.URLConnection; | ||
import java.util.Enumeration; | ||
|
||
import io.quarkus.runtime.annotations.Recorder; | ||
|
||
@Recorder | ||
public class PreloadClassesRecorder { | ||
public static final String QUARKUS_GENERATED_PRELOAD_CLASSES_FILE = "quarkus-generated-preload-classes.txt"; | ||
|
||
public static void preloadClass(String classname, boolean initialize) { | ||
try { | ||
Class.forName(classname, initialize, PreloadClassesRecorder.class.getClassLoader()); | ||
} catch (Throwable ignored) { | ||
|
||
} | ||
} | ||
|
||
public static void preloadClasses(boolean initialize) { | ||
try { | ||
Enumeration<URL> files = PreloadClassesRecorder.class.getClassLoader() | ||
.getResources("META-INF/quarkus-preload-classes.txt"); | ||
while (files.hasMoreElements()) { | ||
URL url = files.nextElement(); | ||
URLConnection conn = url.openConnection(); | ||
conn.setUseCaches(false); | ||
InputStream is = conn.getInputStream(); | ||
preloadClassesFromStream(is, initialize); | ||
} | ||
} catch (IOException ignored) { | ||
} | ||
InputStream is = PreloadClassesRecorder.class | ||
.getResourceAsStream("/META-INF/" + QUARKUS_GENERATED_PRELOAD_CLASSES_FILE); | ||
if (is != null) | ||
preloadClassesFromStream(is, initialize); | ||
} | ||
|
||
public static void preloadClassesFromStream(InputStream is, boolean initialize) { | ||
try (is; | ||
InputStreamReader isr = new InputStreamReader(is); | ||
BufferedReader reader = new BufferedReader(isr)) { | ||
String line; | ||
while ((line = reader.readLine()) != null) { | ||
int idx = line.indexOf('#'); | ||
if (idx != -1) { | ||
line = line.substring(0, idx); | ||
} | ||
final String className = line.stripTrailing(); | ||
if (!className.isBlank()) { | ||
preloadClass(className, initialize); | ||
} | ||
} | ||
} catch (Exception ignored) { | ||
|
||
} | ||
} | ||
|
||
public void invokePreloadClasses(boolean initialize) { | ||
preloadClasses(initialize); | ||
} | ||
} |
Oops, something went wrong.