mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 05:30:43 +00:00
Add Memoization class and supports
This commit is contained in:
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2023. 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.utils.memoization;
|
||||
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for Memoization
|
||||
*******************************************************************************/
|
||||
class MemoizationTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test()
|
||||
{
|
||||
Memoization<String, Integer> memoization = new Memoization<>();
|
||||
memoization.setMaxSize(3);
|
||||
memoization.setTimeout(Duration.ofMillis(100));
|
||||
|
||||
assertThat(memoization.getResult("one")).isEmpty();
|
||||
memoization.storeResult("one", 1);
|
||||
assertThat(memoization.getResult("one")).isPresent().get().isEqualTo(1);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// store 3 more results - this should force 1 out //
|
||||
////////////////////////////////////////////////////
|
||||
memoization.storeResult("two", 2);
|
||||
memoization.storeResult("three", 3);
|
||||
memoization.storeResult("four", 4);
|
||||
assertThat(memoization.getResult("one")).isEmpty();
|
||||
|
||||
//////////////////////////////////
|
||||
// make sure others are present //
|
||||
//////////////////////////////////
|
||||
assertThat(memoization.getResult("two")).isPresent().get().isEqualTo(2);
|
||||
assertThat(memoization.getResult("three")).isPresent().get().isEqualTo(3);
|
||||
assertThat(memoization.getResult("four")).isPresent().get().isEqualTo(4);
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// wait more than the timeout, then make sure all are gone //
|
||||
/////////////////////////////////////////////////////////////
|
||||
SleepUtils.sleep(150, TimeUnit.MILLISECONDS);
|
||||
assertThat(memoization.getResult("two")).isEmpty();
|
||||
assertThat(memoization.getResult("three")).isEmpty();
|
||||
assertThat(memoization.getResult("four")).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
@Disabled("Slow, so not for CI - but good to demonstrate thread-safety during dev")
|
||||
void testMultiThread() throws InterruptedException, ExecutionException
|
||||
{
|
||||
Memoization<String, Integer> memoization = new Memoization<>();
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(20);
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
int finalI = i;
|
||||
futures.add(executorService.submit(() ->
|
||||
{
|
||||
System.out.println("Start " + finalI);
|
||||
for(int n = 0; n < 1_000_000; n++)
|
||||
{
|
||||
memoization.storeResult(String.valueOf(n), n);
|
||||
memoization.getResult(String.valueOf(n));
|
||||
|
||||
if(n % 100_000 == 0)
|
||||
{
|
||||
System.out.format("Thread %d at %,d\n", finalI, +n);
|
||||
}
|
||||
}
|
||||
System.out.println("End " + finalI);
|
||||
}));
|
||||
}
|
||||
|
||||
while(!futures.isEmpty())
|
||||
{
|
||||
Iterator<Future<?>> iterator = futures.iterator();
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
Future<?> next = iterator.next();
|
||||
if(next.isDone())
|
||||
{
|
||||
Object o = next.get();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("All Done");
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user