I am currently working on a benchmark tool for kafka and GC PubSub. I want to see results about min. max and avg transfer speed. In before, i was setting the every entry to reddis hash. After that i was mapping reddis hashes to java map and iterating on them in end of the process for min, max values. It seems so slow because if i call 100000 entry, program iterates x3 for min, max and avg. So i tried to do that with a Lua script. After publishing a message i set a start time to hash map and when listener gets message i take that messages start time from hash and i calculate difference with System.currentTimeMillis
. After this step i am trying to execute Lua Script that compares the current value with older value and sets it. But when i execute the script it seems program stops there. I event tried just returning true from Lua script but i couldn't get any response.
private void calculateSetANDLogAgain(User user){
long startTime = ((long) redisTemplate.opsForHash().get("times", user.getId()));
logger.info("Received message -> " + user.toString());
long duration = 0L;
duration = System.currentTimeMillis() - startTime;
Object[] args = new Object[1];
args[0] = duration;
System.out.println("BEFORE");
boolean a = redisTemplate.execute(statisticScript, Collections.singletonList("a"),args);
System.out.println("AFTER: " + a);
}
Here i see BEFORE but I cant see AFTER printing. Here is the log output and configuration about script executing. And here is my class tree. Note that RedisConfig
class has the bean below.
@Bean
public DefaultRedisScript<Boolean> redisscript(){
DefaultRedisScript defaultRedisScript = new DefaultRedisScript<>();
defaultRedisScript.setLocation(new ClassPathResource("statistics.lua"));
defaultRedisScript.setResultType(Boolean.class);
return defaultRedisScript;
}
And i am autowiring DefaultRedisScript
instance in the class that owns calculateSetANDLogAgain
method. Script file just have "return true;
"
edit; here is my first script if it helps.
local difference = tonumber(ARGV[1])
local max = tonumber(redis.call("GET","max"))
local min = tonumber(redis.call("GET","min"))
if max == nil then
redis.call("SET","max",difference)
elseif difference > max then
redis.call("SET","max",difference)
end
if min == nil then
redis.call("SET","min",difference)
elseif difference < min then
redis.call("SET","min",difference)
end
So what may go wrong? I couldn't figured it out...
I solved the problem. It is bizarre but it seems source of the failure is the wrong classpath. I made some changes in my code so take a look.
Here is the Bean
definition.
@Bean
public DefaultRedisScript<Boolean> redisscript() {
DefaultRedisScript defaultRedisScript = new DefaultRedisScript<Boolean>();
defaultRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("statistics.lua")));
defaultRedisScript.setResultType(Boolean.class);
return defaultRedisScript;
}
Here is the calculateSetANDLogAgain
function.
private void calculateSetANDLogAgain(User user) {
long startTime = ((long) redisTemplate.opsForHash().get("times", user.getId()));
logger.info("Received message -> " + user.toString());
Long duration = null;
duration = System.currentTimeMillis() - startTime;
Object[] args = new Object[1];
args[0] = duration;
try {
redisTemplate.execute(statisticScript, null, args);
} catch (Exception e) {
finalLogger.info("Error while executing script -> " + e.getLocalizedMessage());
}
}
Here is the script;
local difference = tonumber(ARGV[1])
local max = tonumber(redis.call("GET","max"))
local min = tonumber(redis.call("GET","min"))
if max == nil then
redis.call("SET","max",tostring(difference));
elseif difference > max then
redis.call("SET","max",tostring(difference));
end
if min == nil then
redis.call("SET","min",tostring(difference));
elseif difference < min then
redis.call("SET","min",tostring(difference));
end
return nil;
Finally my script in resources folder and i injected the redistemplate in constructor.