@Converter(autoapply=true) slow

Hello,

In our project we have enumerated (no enum java) which must be converted and for that I must recover the type but the mechanism is identical for each.

After a lot of trying to find a solution, I ended up transforming each enumerated into a Converter by applying the AttributeConverter interface to it and @Convert(autoapply=true)

@Converter(autoapply=true)
public class EActivite implements AttributeConverter<EActivite, Short> {
}

The problem with doing this is that we have in our project more than 500 listed (see 1500 but at the moment 500) and as in AttributeConverterManager#locateMatchingConverter it applies each Converter to all attributes this becomes very long.

See below analysis via arthas :

Looking at the possibilities I saw that the registered Conversion ByDomainType map used a much more efficient key/value system on the domain type.

So I had to create a list (I don’t like lists…) in an info-package.java to declare all converters in this way

@ConverterRegistration(converter = CritereConverter.class)
@ConverterRegistration(converter = Currency.class)
@ConverterRegistration(converter = DocumentGenereIsoleConverter.class)
@ConverterRegistration(converter = EAlgorithmeCryptage.class)
@ConverterRegistration(converter = EAmperageUnit.class)
@ConverterRegistration(converter = EAreaUnit.class)
@ConverterRegistration(converter = EEnergyUnit.class)
@ConverterRegistration(converter = EFlowUnit.class)
@ConverterRegistration(converter = EGazCapacityUnit.class)
@ConverterRegistration(converter = EImpedanceUnit.class)
@ConverterRegistration(converter = ElementParametrageConverter.class)
@ConverterRegistration(converter = ELengthUnit.class)
@ConverterRegistration(converter = EMassUnit.class)
@ConverterRegistration(converter = ETemperatureUnit.class)
@ConverterRegistration(converter = ETimeUnit.class)
@ConverterRegistration(converter = EVoltageUnit.class)
@ConverterRegistration(converter = EVolumeUnit.class)
@ConverterRegistration(converter = IImprimanteConverter.class)
@ConverterRegistration(converter = PercentageConverter.class)
@ConverterRegistration(converter = PolitiqueFiltrageConverter.class)
@ConverterRegistration(converter = UndefinedBooleanConverter.class, domainType = boolean.class)
@ConverterRegistration(converter = UndefinedDoubleValueConverter.class, domainType = double.class)
@ConverterRegistration(converter = UndefinedIntValueConverter.class, domainType = int.class)

package com.efluid.hibernate.converter;

import org.hibernate.annotations.ConverterRegistration;

And so I arrive at reasonable times

I wanted to know if you were aware of this, and if my solution seemed correct to you?

Thank you once again.

Sorry, but I don’t understand these images that you posted and also don’t quite understand what you mean by that:

The problem with doing this is that we have in our project more than 500 listed (see 1500 but at the moment 500) and as in AttributeConverterManager#locateMatchingConverter it applies each Converter to all attributes this becomes very long.

Are you saying that something is slow and should be improved? If so, please create a PR with the suggested change and then we can discuss it on the PR.

For the performance images we spend 30’000ms to apply the autoapply of the converters.
If we use @ConversionRegister we are at 700 ms.

In my case I have 500 converters and 800 class attributes

Unfortunately I have no solution to propose to modify the code (see the .5).

  1. Retrieval of the type to apply the converter
  2. This is my solution which is faster, to exploit the registerConversionByDomainType
  3. The performance problem because we loop on all existing converters
  4. In addition to the time-consuming converter application test
  5. It is the verification that only one converter is compatible.
    I tell myself that this is the reason why we loop over all the converters to make sure that we are not multiple compatible converters.

But in itself, we could know it upstream by using a map which also contains the type of the domain as a key.

Please create a JIRA issue for this. There is no reason why @Converter(autoapply=true) should be any slower than @ConverterRegistration.

I created the ticket, is it ok for you?
https://hibernate.atlassian.net/browse/HHH-16129

1 Like

These 2 things are not handled nor applied the same at all. So there is very much a potential for there to be a difference in time to apply.

@ConvertRegistration is new in 6, so that will be hard to compare; but have you tried comparing auto-applied converters in your model between Hibernate 5 and 6?

Thank you for your comeback

Indeed, these are two different applications.
I haven’t tested in 5 but I think the performance issue is the same.

I’m thinking of trying to come up with a solution so I don’t need to create 1000 converter.

In my case I just need to retrieve the final type of the object so I can instantiate it and create a single converter that could retrieve that type and instantiate into the correct type (if I do a generic converter it only knows the parent class for now).

In my example below, XXXXXXX should be replaced by the final type and not by the type of the parent class EnumType :

public class EActivite extends EnumType {}
public class EActivite2 extends EnumType {}
public class EActivite3 extends EnumType {}

@Converter(autoapply=true)
public EnumTypeConverter implements AttributeConverter<EnumType, Short> {
  @Override
  public Short convertToDatabaseColumn(EnumType attribute) {
    return attribute != null ? Integer.valueOf(attribute.getValue()).shortValue() : null;
  }

  @Override
  public EnumType convertToEntityAttribute(Short dbData) {
    return dbData != null ? EnumerationService.instance().find(XXXXXX, dbData) : null;
  }

}