Não pude deixar de ver este tópico que é bem interessante e que não leva a lugar nenhum…
Código abaixo em C++: 6 seg
Equivalente em Java : 13 seg.
char * raw_mem = new char [sizeof (Point)];
for (long i = 0;i < 1000000000; i++) {
Point * x = new (raw_mem) Point(0.0, 0.0);
x->setX(23.98);
x->~Point();
}
delete[] raw_mem;
Você ta chamando o destrutor explicitamente? =Z
Quando fiz isso na faculdade tomei uma bronca do professor que nunca mais ousei fazê-lo novamente hehehe.
O correto não seria um:
Aqui ele mostra o que eu quero dizer com C++ mais otimizável. No C++, você pode fazer seu próprio gerencimento de memória, tanto que ele tentou emular o que o garbage collector já faz nativamente (não apagar a área de memória reservada).
No C++, o correto não seria fazer desse jeito e sim sobrescrever o new e o delete (mas entendo o benchmark feito dessa forma por questões de simplicidade). Agora, isso não é fácil, e o código do colega mostra que a otimização já começou a gerar um programa consideravelmente mais rebuscado. Já seria mais difícil achar gente que sabe fazer algo assim e mais caro manter esse código. Essa otimização também seria impossível caso o objeto tivesse sido criado dentro de um método, como eu sugeri ali em cima, e é sempre existente no Java.
Agora, você diz que o equivalente em Java levou 13 segundos. Qual foi o seu “equivalente em Java”? O código equivalente mais simples e direto é o postaram ali atrás, e na minha máquina levou pouco mais do que meio segundo.
[quote=Tchello] Você ta chamando o destrutor explicitamente? =Z
Quando fiz isso na faculdade tomei uma bronca do professor que nunca mais ousei fazê-lo novamente hehehe.
O correto não seria um:
delete x;
x = NULL;
?[/quote]
Você tem razão. O delete só limpa a área de memória, mas o apontador continua apontando para a area
x---->> 0x???
se x receber null, o ponteiro perde a referencia. É a forma correta de se fazer.
[quote=Tchello] Você ta chamando o destrutor explicitamente? =Z
Quando fiz isso na faculdade tomei uma bronca do professor que nunca mais ousei fazê-lo novamente hehehe.
?[/quote]
Ele chama o destrutor e o construtor explicitamente pois só está interessado no que eles fazem (zerar as variáveis, limpar o ambiente), não na reserva e limpeza da memória. Isso é feito explicitamente por ele, na alocação e desalocação daquele array, e apenas uma vez, antes e depois do for.
Uma coisa interessante aqui. Veja o esforço que estamos fazendo para tentar chegar a um código mais otimizado que o do GC. E mesmo o exemplo extremo do colega ainda levou 6 segundos, contra apenas 1 do Java.
O mais rápido mesmo é alocação e desalocação no stack. Porém, para o programador java, esse gerenciamento é feito de forma transparente, rápida e eficiente pelo gc. Ele em momento nenhum precisou se preocupar com isso ou comprometer a legibilidade do próprio código.
Entretanto, no C++, foi possível chegar a uma solução mais rápida. Poderíamos mesmo sobrescrever o new e o delete, fazer um memory manager otimizado exclusivamente para a classe point, alinhado até mesmo com detalhes de nosso processador. Seria caro, custaria esforço, mas seria possível. Se é viável ou não, só o nosso negócio poderá dizer, mas já vi casos disso na indústria de jogos, por exemplo.
o tipo auto_ptr da biblioteca( #include<memory.h> ) padrão implementa um coletor de lixo automatico, mas não é robusto como o gc do java pelas experiências que tive.
auto_ptr<Pointer> point(new Pointer());
A performance cai consideravelmente. Mas acredito que os smart pointers da boost sejam mais otimizados.