mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Add memoization of constructors in getAdHoc (micro optimization)
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.actions.customizers;
|
package com.kingsrook.qqq.backend.core.actions.customizers;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler;
|
import com.kingsrook.qqq.backend.core.actions.automation.RecordAutomationHandler;
|
||||||
@ -34,30 +35,23 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TableAutomationAction;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TableAutomationAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeFunction;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.memoization.Memoization;
|
||||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Utility to load code for running QQQ customizers.
|
** Utility to load code for running QQQ customizers.
|
||||||
|
**
|
||||||
|
** TODO - redo all to go through method that memoizes class & constructor
|
||||||
|
** lookup. That memoziation causes 1,000,000 such calls to go from ~500ms
|
||||||
|
** to ~100ms.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QCodeLoader
|
public class QCodeLoader
|
||||||
{
|
{
|
||||||
private static final QLogger LOG = QLogger.getLogger(QCodeLoader.class);
|
private static final QLogger LOG = QLogger.getLogger(QCodeLoader.class);
|
||||||
|
|
||||||
|
private static Memoization<String, Constructor<?>> constructorMemoization = new Memoization<>();
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public static <T, R> Optional<Function<T, R>> getTableCustomizerFunction(QTableMetaData table, String customizerName)
|
|
||||||
{
|
|
||||||
Optional<QCodeReference> codeReference = table.getCustomizer(customizerName);
|
|
||||||
if(codeReference.isPresent())
|
|
||||||
{
|
|
||||||
return (Optional.ofNullable(QCodeLoader.getFunction(codeReference.get())));
|
|
||||||
}
|
|
||||||
return (Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -175,8 +169,20 @@ public class QCodeLoader
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Class<?> customizerClass = Class.forName(codeReference.getName());
|
Optional<Constructor<?>> constructor = constructorMemoization.getResultThrowing(codeReference.getName(), (UnsafeFunction<String, Constructor<?>, Exception>) s -> {
|
||||||
return ((T) customizerClass.getConstructor().newInstance());
|
Class<?> customizerClass = Class.forName(codeReference.getName());
|
||||||
|
return customizerClass.getConstructor();
|
||||||
|
});
|
||||||
|
|
||||||
|
if(constructor.isPresent())
|
||||||
|
{
|
||||||
|
return ((T) constructor.get().newInstance());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.error("Could not get constructor for code reference", logPair("codeReference", codeReference));
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.actions.customizers;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.Timer;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for QCodeLoader
|
||||||
|
*******************************************************************************/
|
||||||
|
class QCodeLoaderTest extends BaseTest
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetAdHoc()
|
||||||
|
{
|
||||||
|
QCodeLoader qCodeLoader = QCodeLoader.getAdHoc(QCodeLoader.class, new QCodeReference(QCodeLoader.class));
|
||||||
|
assertThat(qCodeLoader).isInstanceOf(QCodeLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
@Disabled("performance test, used during memoization change")
|
||||||
|
void testBulkPerformance()
|
||||||
|
{
|
||||||
|
Timer timer = new Timer("start");
|
||||||
|
for(int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
useCodeLoader(1_000_000);
|
||||||
|
timer.mark("done with code loader");
|
||||||
|
|
||||||
|
useNew(1_000_000);
|
||||||
|
timer.mark("done with new");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void useNew(int count)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
QCodeLoader qCodeLoader = new QCodeLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void useCodeLoader(int count)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
QCodeLoader qCodeLoader = QCodeLoader.getAdHoc(QCodeLoader.class, new QCodeReference(QCodeLoader.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user