rules engines: faster implementation than methods invocations?

N

NOBODY

Hi,

About rules engines (and jsr-94):
We looked at 'drools', but it uses method invocations.
---> Is there other implementations around, not based on method
invocation?

Given that invocation is 50 to 300 times slower than compiled call,
method invocation sucks big time at high throughputs. My only alternative
is code generation at this point.

Thanks.





-------test code to show invocation cost-------

package tests;

import java.lang.reflect.Method;

public class TestInvokeSpeed {

static Method m_dovoid;
static Method m_dolong;
static Method m_dolongw;

static {
try {
m_dovoid = TestInvokeSpeed.class.getMethod("dovoid", new
Class[]{});
System.out.println(m_dovoid);

m_dolong = TestInvokeSpeed.class.getMethod("dolong", new
Class[]{Long.TYPE, Long.TYPE, String.class, String.class});
System.out.println(m_dolong);

m_dolongw = TestInvokeSpeed.class.getMethod("dolongw",
new Class[]{Long.class, Long.class, String.class, String.class});
System.out.println(m_dolongw);
} catch(Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
int N=40*1000*1000;

testvoid(false, N); System.out.println();
testlong(false, N); System.out.println();
testlongw(false, N); System.out.println();

testvoid(true, N); System.out.println();
testlong(true, N); System.out.println();
testlongw(true, N); System.out.println();

}

static void testvoid(boolean echo, int N) throws Exception {

long t1, d1, d2, d3;

t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
dovoid();
}
d1 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"direct dovoid: total="+d1
+" ms, avg="+(1000.0*d1/N)+" us\n");


t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
m_dovoid.invoke(null, null);
}
d2 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"invoke dovoid+null: total="+d2
+" ms ("+(1.0*d2/d1)+"x), avg="+(1000.0*d2/N)+" us\n");


Object[] args = new Object[0];
t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
m_dovoid.invoke(null, args);
}
d3 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"invoke dovoid: total="+d3
+" ms ("+(1.0*d3/d1)+"x), avg="+(1000.0*d3/N)+" us\n");
}



static void testlong(boolean echo, int N) throws Exception {
long t1, d1, d2;

t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
long l = dolong(1, 2, "toto", "tata");
}
d1 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"direct dolong: total="+d1
+" ms, avg="+(1000.0*d1/N)+" us\n");


Object[] args = new Object[]{new Long(1), new Long(2), "toto",
"tata"};
t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
long l = ((Long)m_dolong.invoke(null, args)).longValue();
}
d2 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"invoke dolong: total="+d2
+" ms ("+(1.0*d2/d1)+"x), avg="+(1000.0*d2/N)+" us\n");

}

static void testlongw(boolean echo, int N) throws Exception {
long t1, d1, d2;

Long l1 = new Long(1);
Long l2 = new Long(2);

t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
Long l = dolongw(l1, l2, "toto", "tata");
}
d1 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"direct dolongw: total="+d1
+" ms, avg="+(1000.0*d1/N)+" us\n");


Object[] args = new Object[]{new Long(1), new Long(2), "toto",
"tata"};
t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
Long l = (Long)m_dolong.invoke(null, args);
}
d2 = System.currentTimeMillis()-t1;
System.out.print(!echo?".":"invoke dolongw: total="+d2
+" ms ("+(1.0*d2/d1)+"x), avg="+(1000.0*d2/N)+" us\n");

}



public static void dovoid() {}

public static long dolong(long l1, long l2, String s1, String s2) {
return 0;
}

public static Long dolongw(Long l1, Long l2, String s1, String s2) {
return null;
}


}
 
J

Jesper Nordenberg

NOBODY said:
Hi,

About rules engines (and jsr-94):
We looked at 'drools', but it uses method invocations.
---> Is there other implementations around, not based on method
invocation?

Given that invocation is 50 to 300 times slower than compiled call,
method invocation sucks big time at high throughputs. My only alternative
is code generation at this point.

You're benchmark is not very accurate. I've modified it so it actually
does some work and removed the object <-> primitive conversions. The
results using JDK 1.5 -server are:

direct dolong: total=3205 ms, avg=0.080125 us, 440000000
invoke dolong: total=4536 ms (1.4152886115444618x), avg=0.1134 us,
440000000

So, the difference in speed is not as big as you suggest.

/Jesper Nordenberg

public class TestInvokeSpeed {

static Method m_dolong;

static {
try {
m_dolong = TestInvokeSpeed.class.getMethod("dolong", new
Class[]{Long.class,

Long.class,

String.class,

String.class});
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
int N = 40 * 1000 * 1000;

testlong(false, N);
System.out.println();

testlong(true, N);
System.out.println();

}

static void testlong(boolean echo, int N) throws Exception {
long t1, d1, d2;

t1 = System.currentTimeMillis();
long l = 0;
Long l1 = new Long(1);
Long l2 = new Long(2);

for (int i = 0; i < N; i++) {
l += dolong(l1, l2, "toto", "tata").longValue();
}

d1 = System.currentTimeMillis() - t1;
System.out.println(!echo ? "." : "direct dolong: total=" + d1 + "
ms, avg=" + (1000.0 * d1 / N) + " us, " + l);


Object[] args = new Object[]{new Long(1), new Long(2), "toto",
"tata"};

t1 = System.currentTimeMillis();
l = 0;

for (int i = 0; i < N; i++) {
l += ((Long) m_dolong.invoke(null, args)).longValue();
}

d2 = System.currentTimeMillis() - t1;
System.out.println(!echo ? "." : "invoke dolong: total=" + d2
+ " ms (" + (1.0 * d2 / d1) +
"x), avg=" + (1000.0 * d2 / N) + " us, " + l);

}

public static Long dolong(Long l1, Long l2, String s1, String s2) {
return new Long(l1.longValue() + l2.longValue() + s1.length() +
s2.length());
}

}
 
N

NOBODY

You're benchmark is not very accurate. I've modified it so it actually
does some work and removed the object <-> primitive conversions. The
results using JDK 1.5 -server are:

direct dolong: total=3205 ms, avg=0.080125 us, 440000000
invoke dolong: total=4536 ms (1.4152886115444618x), avg=0.1134 us,
440000000

So, the difference in speed is not as big as you suggest.

[....]
public static Long dolong(Long l1, Long l2, String s1, String s2) {
return new Long(l1.longValue() + l2.longValue() + s1.length() +
s2.length());
}
}


My test was fine, accurate and thought through.
You just threw all mesurements off... Here's why in 3 reasons:

1---
you are measuring the time of the behavior of the method, not the method
call. You suggest that the overhead would be negligible if the body was
working more. True. But I wanted to compare the cost of calls, because
for a rule engine, the operations are often very short. Rules can be as
simple as 1 single equality '==' operation. Even with:

public static long dolong(long l1, long l2, String s1, String s2) {
return l1+l2+s1.length()+s2.length();
}

I get 35x:
direct dolong: total=62 ms, avg=0.0062 us
invoke dolong: total=2016 ms (32.516129032258064x), avg=0.2016 us


2---
you force the memory trashing (with Long wrapper) that I explicitely
wanted to avoid. I DO want to use primitive, for obvious speed gain. I
know reflection wraps/unwraps. I actually took the time to write the args
array only once to avoid that wrapping overhead, and limit the extra
invocation work to unwrapping. It is not my choice if reflection api is
too limited to handle primitive. So it is part of the cost of invocation,
which is the purpose of the test.

3---
You introduced an extra sum and .longValue in the for loop, screwing the
timing again by adding behavior time instead of constraining the test to
method call time.


********** So, back to the question: **********

Are there rules engine implementations not relying on method invocation
(compiled code, I guess)?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top