stash in a static field, the list set of topLevel classes (performance gain for setups where this class is called multiple times (along with clearing that cache during a javalin instance hotswap)

This commit is contained in:
2024-05-10 12:24:29 -05:00
parent 81a5d868b6
commit 196488ad6e
2 changed files with 41 additions and 3 deletions

View File

@ -30,6 +30,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath; import com.google.common.reflect.ClassPath;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.logging.QLogger;
@ -50,6 +51,8 @@ public class MetaDataProducerHelper
private static Map<Class<?>, Integer> comparatorValuesByType = new HashMap<>(); private static Map<Class<?>, Integer> comparatorValuesByType = new HashMap<>();
private static Integer defaultComparatorValue; private static Integer defaultComparatorValue;
private static ImmutableSet<ClassPath.ClassInfo> topLevelClasses;
static static
{ {
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -70,8 +73,6 @@ public class MetaDataProducerHelper
comparatorValuesByType.put(QAppMetaData.class, 23); comparatorValuesByType.put(QAppMetaData.class, 23);
} }
/******************************************************************************* /*******************************************************************************
** Recursively find all classes in the given package, that implement MetaDataProducerInterface ** Recursively find all classes in the given package, that implement MetaDataProducerInterface
** run them, and add their output to the given qInstance. ** run them, and add their output to the given qInstance.
@ -186,7 +187,7 @@ public class MetaDataProducerHelper
List<Class<?>> classes = new ArrayList<>(); List<Class<?>> classes = new ArrayList<>();
ClassLoader loader = Thread.currentThread().getContextClassLoader(); ClassLoader loader = Thread.currentThread().getContextClassLoader();
for(ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) for(ClassPath.ClassInfo info : getTopLevelClasses(loader))
{ {
if(info.getName().startsWith(packageName)) if(info.getName().startsWith(packageName))
{ {
@ -197,4 +198,29 @@ public class MetaDataProducerHelper
return (classes); return (classes);
} }
/*******************************************************************************
**
*******************************************************************************/
private static ImmutableSet<ClassPath.ClassInfo> getTopLevelClasses(ClassLoader loader) throws IOException
{
if(topLevelClasses == null)
{
topLevelClasses = ClassPath.from(loader).getTopLevelClasses();
}
return (topLevelClasses);
}
/*******************************************************************************
**
*******************************************************************************/
public static void clearTopLevelClassCache()
{
topLevelClasses = null;
}
} }

View File

@ -103,6 +103,7 @@ import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSo
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerHelper;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType; import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
@ -283,6 +284,14 @@ public class QJavalinImplementation
try try
{ {
////////////////////////////////////////////////////////////////////////////////
// clear the cache of classes in this class, so that new classes can be found //
////////////////////////////////////////////////////////////////////////////////
MetaDataProducerHelper.clearTopLevelClassCache();
/////////////////////////////////////////////////
// try to get a new instance from the supplier //
/////////////////////////////////////////////////
QInstance newQInstance = qInstanceHotSwapSupplier.get(); QInstance newQInstance = qInstanceHotSwapSupplier.get();
if(newQInstance == null) if(newQInstance == null)
{ {
@ -290,6 +299,9 @@ public class QJavalinImplementation
return; return;
} }
///////////////////////////////////////////////////////////////////////////////////
// validate the instance, and only if it passes, then set it in our static field //
///////////////////////////////////////////////////////////////////////////////////
new QInstanceValidator().validate(newQInstance); new QInstanceValidator().validate(newQInstance);
QJavalinImplementation.qInstance = newQInstance; QJavalinImplementation.qInstance = newQInstance;
LOG.info("Swapped qInstance"); LOG.info("Swapped qInstance");