Percebi degradação significativa de desempenho ao passar da versão 3.5.1 para a versão 3.10.1 (Dropwizard 1.3.5 -> 2.0.X) ao usar mapeadores de linha e argumento Java Beans para tipos Java com mais de 20 campos.
Criei um programa de micro benchmark: https://github.com/Alexey1Gavrilov/jdbi-test para reproduzir o problema. O tempo de execução em 3.5.1 e 3.10.1 pode ser diferente de até 70%
Olá @ Alexey1Gavrilov , obrigado por relatar isso! Eu concordo que definitivamente houve algumas regressões.
Comecei a trabalhar para melhorar a situação: https://github.com/jdbi/jdbi/pull/1607
Atualmente, está apenas esperando uma revisão e alguns testes para garantir que não quebramos tudo :)
Você tem algum tempo para verificar de forma independente se as correções vinculadas acima ajudam no seu caso de uso?
Obrigado e esperamos ter uma correção incorporada em breve.
Uma ótima notícia que você já está trabalhando na melhoria! Posso confirmar que o # 1607 melhora significativamente o desempenho. Meu programa de micro benchmark é executado aproximadamente 10-15% mais rápido com aquele PR, do que no 3.5.1. Ótimo trabalho!
Também implementamos uma camada de cache customizada para o matcher de nome de coluna que melhora o desempenho ainda mais. A ideia era basicamente armazenar em cache a comparação de columnName
e javaName
para todos os campos processados pela instância Jdbi
. Aqui está um snippet de código:
class CachingColumnNameMatcher implements ColumnNameMatcher {
private static class Column {
final String columnName;
final String javaName;
private Column(String columnName, String javaName) {
this.columnName = columnName;
this.javaName = javaName;
}
<strong i="10">@Override</strong>
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Column column = (Column) o;
return Objects.equals(columnName, column.columnName) &&
Objects.equals(javaName, column.javaName);
}
<strong i="11">@Override</strong>
public int hashCode() {
return Objects.hash(columnName, javaName);
}
}
private final ColumnNameMatcher delegate;
private final ConcurrentMap<Column, Boolean> cache;
CachingColumnNameMatcher(final ColumnNameMatcher delegate) {
this.delegate = delegate;
this.cache = new ConcurrentHashMap<>();
}
<strong i="12">@Override</strong>
public boolean columnNameMatches(final String columnName, final String javaName) {
final Column key = new Column(columnName, javaName);
return cache.computeIfAbsent(key, (c) -> delegate.columnNameMatches(columnName, javaName));
}
}
...
final ReflectionMappers reflectionMappers = jdbi.getConfig().get(ReflectionMappers.class);
reflectionMappers.setColumnNameMatchers(
reflectionMappers.getColumnNameMatchers().stream()
.map(CachingColumnNameMatcher::new)
.collect(Collectors.toList()));
...
Por favor, deixe-me saber se a comparação do nome da coluna de cache faz sentido para você (ela vem com algum custo de coleta de lixo), se eu puder abrir um PR.
@ Alexey1Gavrilov , acabei de lançar 3.11.0 com # 1607 incluído.
Estou feliz em melhorar o desempenho da correspondência de nomes de coluna, embora armazenar em cache todas as correspondências seja, possivelmente, uma solução pesada. Você está tendo problemas com um matcher específico - o matcher SnakeCase talvez? Vamos começar com uma descrição melhor do problema que está afetando você e encontrar uma solução, que pode ser o cache :)
3.11.1 testado - melhoria de 20% em comparação com 3.5.1! Ótimo trabalho!
Vou criar um problema separado no matcher SnakeCase e discutiremos as possíveis soluções lá.
Perfeito, obrigado!
Comentários muito úteis
3.11.1 testado - melhoria de 20% em comparação com 3.5.1! Ótimo trabalho!
Vou criar um problema separado no matcher SnakeCase e discutiremos as possíveis soluções lá.