Skip to content

Commit

Permalink
Fall back properly to automatically-chosen factory classes if the cho…
Browse files Browse the repository at this point in the history
…sen one isn't working.

Don't bother benchmarking the chosen factory class; it either works or it doesn't.
  • Loading branch information
JonathanLennox committed Sep 21, 2020
1 parent 37e6b1a commit b81f28c
Showing 1 changed file with 65 additions and 41 deletions.
106 changes: 65 additions & 41 deletions src/main/java/org/jitsi/srtp/crypto/Aes.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,7 @@ public void run(Cipher cipher) throws Exception
private static CipherFactory benchmark(
CipherFactory[] factories,
int keySize,
String transformation,
boolean warmup
String transformation
)
{
long minTime = Long.MAX_VALUE;
Expand All @@ -285,6 +284,14 @@ private static CipherFactory benchmark(
if (factory == null)
continue;

// The user may have specified a specific CipherFactory class
// (name) through setFactoryClassName(String), Practically, FACTORY_CLASS_NAME may override
// minFactory and, consequently, it may appear that the benchmark is
// unnecessary. Technically though, the specified CipherFactory may
// malfunction. That is why FACTORY_CLASS_NAME is selected after it has
// proven itself functional.
boolean chosenFactoryClass = (factory.getClass().equals(Aes.factoryClass));

try
{
Cipher cipher = factory.createCipher(transformation);
Expand All @@ -298,18 +305,24 @@ private static CipherFactory benchmark(
}
else
{
/* If this is the user-chosen factory class, we don't really
* need to benchmark it; just verify that it's working.
*/
int numWarmups = chosenFactoryClass ? 0 : NUM_WARMUPS;
int numBenchmarks = chosenFactoryClass ? 1 : NUM_BENCHMARKS;

BenchmarkOperation benchmark = BenchmarkOperation.getBenchmark(transformation, keySize);
if (warmup)
if (!chosenFactoryClass)
{
// Let the JVM "warm up" (do JIT compilation and the like)
for (int i = 0; i < NUM_WARMUPS; i++)
for (int i = 0; i < numWarmups; i++)
{
benchmark.run(cipher);
}
}

long startTime = System.nanoTime();
for (int i = 0; i < NUM_BENCHMARKS; i++)
for (int i = 0; i < numBenchmarks; i++)
{
benchmark.run(cipher);
}
Expand Down Expand Up @@ -338,6 +351,19 @@ private static CipherFactory benchmark(
else if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
}

if (chosenFactoryClass)
{
if (minFactory != null)
{
return minFactory;
}
else
{
logger.warn("Chosen factory class \"" + FACTORY_CLASS_NAME +
"\" not working for " + transformation);
}
}
}

if (log.length() != 0)
Expand Down Expand Up @@ -540,26 +566,47 @@ else if (t instanceof ThreadDeath)

// If FACTORY_CLASS_NAME does not specify a well-known Class, add the
// new Class to FACTORY_CLASSES.
if (add && (factoryClass != null))
if (factoryClass != null)
{
for (Class<?> clazz : factoryClasses)
Class<?>[] newFactoryClasses;
if (add)
{
if (factoryClass.equals(clazz))
for (Class<?> clazz : factoryClasses)
{
add = false;
break;
if (factoryClass.equals(clazz))
{
add = false;
break;
}
}
}
if (add)
{
Class<?>[] newFactoryClasses
= new Class<?>[1 + factoryClasses.length];
if (add)
{
newFactoryClasses
= new Class<?>[1 + factoryClasses.length];

newFactoryClasses[0] = factoryClass;
System.arraycopy(
newFactoryClasses[0] = factoryClass;
System.arraycopy(
factoryClasses, 0,
newFactoryClasses, 1,
factoryClasses.length);
}
}
else
{
/* Otherwise, move the FACTORY_CLASS to the beginning of the list. */
newFactoryClasses
= new Class<?>[factoryClasses.length];

newFactoryClasses[0] = factoryClass;
int i = 1;
for (Class<?> clazz : factoryClasses)
{
if (!factoryClass.equals(clazz))
{
newFactoryClasses[i] = clazz;
i++;
}
}
factoryClasses = newFactoryClasses;
}
}
Expand Down Expand Up @@ -642,30 +689,7 @@ private static CipherFactory getCipherFactory(String transformation, boolean war
// Benchmark the StreamCiphers provided by the available
// StreamCipherFactories in order to select the fastest-performing
// CipherFactory.
CipherFactory minFactory = benchmark(factories, keySize, transformation, warmup);

// The user may have specified a specific CipherFactory class
// (name) through setFactoryClassName(String), Practically, FACTORY_CLASS_NAME may override
// minFactory and, consequently, it may appear that the benchmark is
// unnecessary. Technically though, the specified CipherFactory may
// malfunction. That is why FACTORY_CLASS_NAME is selected after it has
// proven itself functional.
{
Class<? extends CipherFactory> factoryClass = Aes.factoryClass;

if (factoryClass != null)
{
for (CipherFactory factory : factories)
{
if ((factory != null)
&& factory.getClass().equals(factoryClass))
{
minFactory = factory;
break;
}
}
}
}
CipherFactory minFactory = benchmark(factories, keySize, transformation);

return minFactory;
}
Expand Down

0 comments on commit b81f28c

Please sign in to comment.