Oi Mussatto,
sobre performance, a melhor dica que tenho é... ciência da computação.
Sério mesmo: sempre se lembrar das aulas de algoritmos e estruturas de dados que vimos na faculdade. Isto ajuda muito na hora de pensar como executar o processamento, etc.
Uma dica interessante que dou é a seguinte: se você está trabalhando com processamento em lote de registros no banco de dados relacional, use JDBC nativo ao invés do GORM: sua performance sempre vai ser ordens de magnitude superior. Porém, não do modo como os caras dizem pra usar, mas de uma maneira alternativa, tal como no código abaixo:
class ServicoBrutoService {
// injete o sessionFactory diretamente no seu serviço
def sessionFactory
// trabalhando com JDBC direto
def processamentoBruto() {
// Repare como obtive a conexão
def conexao = sessionFactory.currentSession.connection()
}
}
No modo como obtive a conexão, eu ainda estou dentro do contexto transacional do service, a diferença é que estou bypassando o GORM e o Hibernate completamente. Com isto eu evito problemas decorrentes de preenchimento de sesssão para atualizar estados dos objetos (muita atenção com este ponto) e consigo executar o processamento ordens de magnitude mais rápido.
Sobre os problemas de permgen, eu tenho uma solução que ajuda a economizar boa parte da sua memória. O que rola: toda closure que você implementa no seu código groovy no final das contas vai virar um .class. Então, o ideal é que você minimize isto ao máximo, porém sem perder a grande vantagem da linguagem que é justamente este construtor.
Então, como eu resolvo o problema? Simples: eu reaproveito a closure! Hà diversas closures que são exatamente iguais, como no exemplo abaixo em que eu ordeno três listas de pessoas, observe:
def pessoasFisicas = obterPessoasFisicas() // obtenho a lista de pessoas fisicas
def pessoasJuridicas = obterPessoasJuridicas()
def pessoasEsquisitas = obterPessoasEsquisitas()
// em seguida, eu as ordeno
pessoasFisicas.sort {it.nome}
pessoasJuridicas.sort {it.nome}
pessoasEsquisitas.sort {it.nome}
// repare que é a mesma closure implementada três vezes acima. Como resolvo? assim:
def closureOrdenacao = {it.nome}
// eu a reaproveito
pessoasFisicas.sort closureOrdenacao
pessoasJuridicas.sort closureOrdenacao
pessoasEsquisitas.sort closureOrdenacao
Uma solução é ter estas closures por exemplo todas agrupadas em uma única classe que você reaproveita pelo seu código fonte inteiro. Isto costuma gerar uma economia monstruosa de memória e ainda modulariza melhor o seu código.