Por que o código Java gerado para executar uma operação executar mais lentamente do que um “loop de intérprete”?

StackOverflow https://stackoverflow.com/questions/875695

Pergunta

Eu tenho algum código Java que executa bit a bit operações em um BitSet. Eu tenho uma lista de operações e pode "interpretar" -los por looping sobre eles, mas é importante para mim que eu posso realizar estas operações o mais rápido possível, assim que eu venho tentando gerar dinamicamente código para aplicá-las. Eu gerar fonte Java para executar as operações e compilar uma classe que implementa essas operações usando Javassist.

Infelizmente, o meu código gerado dinamicamente é executado mais lentamente do que o código interpretado. Parece que isso é porque HotSpot é otimizar o código interpretado, mas não é otimizar o código compilado: Depois que eu executá-lo alguns milhares de vezes, o meu código interpretado corre duas vezes mais rápido como fez inicialmente, mas meus shows código compilado sem speedup. Consistente com esta hipótese, o meu código interpretado inicialmente é mais lento do que o código compilado, mas é, eventualmente, mais rápido.

Eu não sei por que isso está acontecendo. Meu palpite é que talvez Javassist usa um carregador de classe cujas aulas não HotSpot não toque. Mas eu não sou especialista em carregamento de classe em Java, então eu não tenho certeza se isso é uma suposição razoável ou como proceder para testá-lo. Aqui está como eu estou criando e carregar a classe com Javassist:

ClassPool pool = ClassPool.getDefault();
CtClass tClass = pool.makeClass("foo");

// foo implements MyInterface, with one method
tClass.addInterface(pool.get(MyInterface.class.getName()));

// Get the source for the method and add it
CtMethod tMethod = CtNewMethod.make(getSource(), tClass);
tClass.addMethod(tMethod);

// finally, compile and load the class
return (MyInterface)tClass.toClass().newInstance();

Alguém tem uma idéia sobre o que está acontecendo aqui? Eu realmente aprecio qualquer ajuda que você pode dar.

Eu estou usando o servidor Sun 1.6 JVM no Windows XP 32-bit.

Foi útil?

Solução

HotSpot não se importa onde o código vem. Por exemplo, ele vai código feliz em linha chamada através de uma chamada de método virtual com uma implementação carregado por um carregador de classe diferente.

Eu sugiro que você escrever em código-fonte as operações que você está tentando realizar para esta referência, e em seguida, referência que. É geralmente mais fácil de escrever um exemplo de código gerado em vez de escrever o gerador de qualquer maneira.

Há uma série de razões pelas quais HotSpot pode não código otimizar tão duro como pôde. Por exemplo métodos muito longos tenderá a não ser embutido ou que tenham método embutido neles.

Outras dicas

Eu acho que entendo o que estava acontecendo aqui. Meu primeiro erro foi gerando métodos que eram demasiado longo. Depois que eu fixo que, notei que, embora o meu código gerado foi ainda mais lento, ele finalmente se aproximou da velocidade do código interpretado.

Eu acho que o maior aumento de velocidade aqui vem de HotSpot otimizar meu código. Na versão interpretada, há muito pouco código para otimizar, de modo HotSpot rapidamente cuida dele. Na versão gerado, há um monte de código para otimizar, de modo HotSpot leva mais tempo para trabalhar sua mágica sobre todo o código.

Se eu correr meus pontos de referência para o tempo suficiente, eu agora ver meu código gerado realizando apenas um pouco melhor do que o código interpretado.

Há uma configuração de JVM que controla o quão rápido código deve ser compilados XX: CompileThreshold = 10000

Número de chamadas de método / galhos antes de compilar [-client: 1.500]

Eu não sei se isso vai ajudar, porque no seu exemplo, o tamanho parecem desempenhar um papel vital.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top