Перед написанием такого бенчмарка (и особенно бенчмарка с использованием JVM) необходимо учесть несколько моментов:
на большинстве (физических) машин Redis может обрабатывать более 100 000 операций в секунду при использовании конвейерной обработки. Ваш тест работает только с 100 000 элементов, поэтому он не длится достаточно долго, чтобы давать значимые результаты. Кроме того, нет времени для запуска последовательных этапов JIT.
абсолютное время не очень релевантная метрика. Отображение пропускной способности (т. е. количества операций в секунду) при сохранении работы теста в течение не менее 10 секунд было бы лучшим и более стабильным показателем.
ваш внутренний цикл генерирует много мусора. Если вы планируете проводить бенчмаркинг Jedis+Redis, вам нужно поддерживать низкую нагрузку на собственную программу.
поскольку вы определили все в основную функцию, ваш цикл не будет скомпилирован JIT (в зависимости от используемой вами JVM). Могут быть только внутренние вызовы методов. Если вы хотите, чтобы JIT был эффективным, обязательно инкапсулируйте свой код в методы, которые могут быть скомпилированы JIT.
при желании вы можете добавить фазу прогрева перед выполнением фактического измерения, чтобы избежать накладных расходов на выполнение первых итераций с помощью базового интерпретатора и стоимости самой JIT.
Теперь, что касается конвейеризации Redis, ваш конвейер слишком длинный. 100 000 команд в конвейере означают, что Jedis должны создать буфер размером 6 МБ, прежде чем отправлять что-либо в Redis. Это означает, что буферы сокетов (на стороне клиента и, возможно, на стороне сервера) будут заполнены, и что Redis также придется иметь дело с коммуникационными буферами размером 6 МБ.
Кроме того, ваш тест по-прежнему синхронен (использование конвейера не делает его волшебным образом асинхронным). Другими словами, Jedis не начнет читать ответы, пока последний запрос вашего конвейера не будет отправлен в Redis. Когда конвейер слишком длинный, он может заблокировать работу.
Рассмотрите возможность ограничения размера конвейера до 100–1000 операций. Конечно, это будет генерировать больше циклов, но нагрузка на коммуникационный стек будет снижена до приемлемого уровня. Например, рассмотрим следующую программу:
import redis.clients.jedis.*;
import java.util.*;
public class TestPipeline {
/**
* @param args
*/
int i = 0;
Map<String, String> map = new HashMap<String, String>();
ShardedJedis jedis;
// Number of iterations
// Use 1000 to test with the pipeline, 100 otherwise
static final int N = 1000;
public TestPipeline() {
JedisShardInfo si = new JedisShardInfo("127.0.0.1", 6379);
List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
list.add(si);
jedis = new ShardedJedis(list);
}
public void push( int n ) {
ShardedJedisPipeline pipeline = jedis.pipelined();
for ( int k = 0; k < n; k++) {
map.put("id", "" + i);
map.put("name", "lyj" + i);
pipeline.hmset("m" + i, map);
++i;
}
pipeline.sync();
}
public void push2( int n ) {
for ( int k = 0; k < n; k++) {
map.put("id", "" + i);
map.put("name", "lyj" + i);
jedis.hmset("m" + i, map);
++i;
}
}
public static void main(String[] args) {
TestPipeline obj = new TestPipeline();
long startTime = System.currentTimeMillis();
for ( int j=0; j<N; j++ ) {
// Use push2 instead to test without pipeline
obj.push(1000);
// Uncomment to see the acceleration
//System.out.println(obj.i);
}
long endTime = System.currentTimeMillis();
double d = 1000.0 * obj.i;
d /= (double)(endTime - startTime);
System.out.println("Throughput: "+d);
}
}
С помощью этой программы вы можете тестировать с конвейерной обработкой или без нее. Обязательно увеличьте количество итераций (параметр N) при использовании конвейерной обработки, чтобы она выполнялась не менее 10 секунд. Если вы раскомментируете println в цикле, вы поймете, что программа работает медленно в начале и будет работать быстрее, когда JIT начнет оптимизировать вещи (поэтому программа должна работать как минимум несколько секунд, чтобы дать значимый результат).
На моем оборудовании (старый Athlon) я могу получить в 8-9 раз больше пропускной способности при использовании конвейера. Программу можно улучшить, оптимизировав форматирование ключей/значений во внутреннем цикле и добавив фазу прогрева.
person
Didier Spezia
schedule
23.05.2013
1,000,000 inserts took 1.208 seconds
на моем ноутбуке. - person Peter Lawrey   schedule 22.05.2013