Quão mais rápido é C ++ que C #?

245

Ou agora é o contrário?

Pelo que ouvi, há algumas áreas em que o C # prova ser mais rápido que o C ++, mas nunca tive coragem de testá-lo sozinho.

Pensei que algum de vocês pudesse explicar essas diferenças em detalhes ou me indicar o lugar certo para obter informações sobre isso.

Armadilha
fonte
7
Protegido, para impedir que mais benchmarks aleatórios sejam publicados. Se você acha que pode argumentar, precisará de 10 representantes para fazê-lo.
Robert Harvey
2
Como isso não é encerrado como opinião / argumentativo? Ainda não estou no StackOverflow? (Não sugerindo o fechamento, apenas curioso. Adoro perguntas que estimulam argumentos opinativos) #
K Bill Bill
1
É quase uma questão discutível, uma vez que vivemos em uma época em que IL pode ser convertido para CPP e otimizado de lá: docs.unity3d.com/Manual/IL2CPP.html
pixelpax
Um idioma que verifica o acesso fora da faixa de alcance nunca supera o que não é.
Seva Alekseyev
@SevaAlekseyev Não é o idioma que faz isso, mas o compilador. Uma das razões pelas quais o C ++ é tão rápido (além dos óbvios) é que os compiladores do C ++ existem há 35 anos (se não mais). Não há nada que impeça os compiladores de C # de melhorar com o tempo. Para o caso mencionado, leia este stackoverflow.com/questions/16713076/…
Trap

Respostas:

342

Não há uma razão estrita pela qual uma linguagem baseada em bytecode como C # ou Java que possua um JIT não possa ser tão rápida quanto o código C ++. No entanto, o código C ++ costumava ser significativamente mais rápido por um longo tempo, e também hoje ainda é em muitos casos. Isso ocorre principalmente porque as otimizações de JIT mais avançadas são complicadas de implementar, e as realmente legais estão chegando apenas agora.

Portanto, o C ++ é mais rápido, em muitos casos. Mas isso é apenas parte da resposta. Os casos em que o C ++ é realmente mais rápido são programas altamente otimizados, em que programadores especializados otimizam completamente o inferno. Isso não apenas consome muito tempo (e, portanto, caro), mas também geralmente leva a erros devido a super otimizações.

Por outro lado, o código nas linguagens interpretadas fica mais rápido nas versões posteriores do tempo de execução (.NET CLR ou Java VM), sem que você faça nada. E há muitas otimizações úteis que os compiladores JIT podem fazer que são simplesmente impossíveis em linguagens com ponteiros. Além disso, alguns argumentam que a coleta de lixo geralmente deve ser tão rápida ou mais rápida quanto o gerenciamento manual de memória e, em muitos casos, é. Geralmente, você pode implementar e conseguir tudo isso em C ++ ou C, mas será muito mais complicado e propenso a erros.

Como Donald Knuth disse, "a otimização prematura é a raiz de todo mal". Se você realmente tem certeza de que seu aplicativo consistirá principalmente de aritmética crítica de desempenho, e que será o gargalo, e certamente será mais rápido em C ++, e você tem certeza de que C ++ não entrará em conflito com seu outro requisitos, vá para C ++. Em qualquer outro caso, concentre-se em primeiro implementar seu aplicativo corretamente no idioma que melhor lhe convier, depois encontre gargalos de desempenho se ele ficar muito lento e pense em como otimizar o código. Na pior das hipóteses, pode ser necessário chamar o código C por meio de uma interface de função externa, para que você ainda possa escrever partes críticas em linguagem de nível inferior.

Lembre-se de que é relativamente fácil otimizar um programa correto, mas é muito mais difícil corrigir um programa otimizado.

Fornecer porcentagens reais de vantagens de velocidade é impossível, pois depende muito do seu código. Em muitos casos, a implementação da linguagem de programação não é nem o gargalo. Considere os benchmarks em http://benchmarksgame.alioth.debian.org/ com muito ceticismo, pois eles testam amplamente o código aritmético, que provavelmente não é nem um pouco parecido com o seu código.

Martin Probst
fonte
92
o código nas linguagens interpretadas fica mais rápido nas versões posteriores do tempo de execução. O código compilado por uma versão melhor do compilador também fica mais rápido.
Martin York
47
De fato, há pelo menos um motivo: o JIT precisa ser rápido e não pode gastar tempo em várias otimizações avançadas disponíveis para um compilador C ++.
Nemanja Trifunovic
63
"mas também geralmente leva a erros devido a super otimizações". [citação necessária desesperadamente]. Eu trabalho em um laboratório nacional e otimizamos muito o nosso código. Isso geralmente não resulta em código de buggy.
Todd Gamblin
35
"É relativamente fácil otimizar um programa correto, mas muito mais difícil corrigir um programa otimizado".
Gradbot 17/07/10
20
Inge: não sei se você está no caminho certo. Sim, o C # é implementado em outro idioma, mas o compilador JIT está gerando código de máquina, portanto, não é um idioma interpretado. Portanto, não é limitado por sua implementação em C ++. Não sei ao certo por que você acha que adicionar algum gerente a algo inerentemente o torna mais rápido.
Martin Probst
202

O c # pode não ser mais rápido, mas torna VOCÊ / ME mais rápido. Essa é a medida mais importante para o que faço. :)

mattlant
fonte
68
Haha, há uma boa citação de Larry Wall sobre o assunto. Ele está falando sobre perl, mas isso pode ser pensado em todas as discussões que envolvem idiomas e desempenho: ".. linguagens de computador anteriores, como Fortran e C, foram projetadas para fazer uso eficiente de hardware de computador caro. Por outro lado, o Perl foi projetado para fazer uso eficiente dos programadores de computador caros"
Falaina
60
1. "C # é muito mais rápido que C ++" 2. "Não pode ser verdade" 1. "Claro que pode" 2. "Em quanto?" 1. "Geralmente por 3-4 meses"
Dmitry S.
2
para C ++ que realmente depende das bibliotecas a sua usando, C # não é normalmente mais rápido, .NET é, quando você está falando de produtividade
Ion Todirel
É a mesma razão pela qual você pode usar Python em vez de C para escrever algum código ... mas, depois de criar alguns cálculos pesados, você pode sentir a diferença no desempenho.
precisa saber é o seguinte
Isso depende do que você está acostumado. Eu programa muito mais rápido em C ++ do que teria em C #. O conhecimento da biblioteca é uma grande parte disso, pois você não deseja reinventar a roda para tarefas básicas. O principal problema do C / C ++ era o gerenciamento de ponteiros, que é praticamente resolvido com ponteiros inteligentes. Dito isto, o C ++ sério carece de uma biblioteca extensa, como o .NET e o Java oferecem, e isso pode acelerar o desenvolvimento em grande parte. Isso não será resolvido em breve, uma vez que esses garotos comuns gostam de gastar seu tempo em melhorias de modelo em vez de extensões de biblioteca.
gast128 26/02
87

São cinco laranjas mais rápidas. Ou melhor: não pode haver resposta (correta) geral. C ++ é uma linguagem compilada estaticamente (mas também há otimização guiada por perfil), execuções de C # auxiliadas por um compilador JIT. Existem tantas diferenças que perguntas como "quanto mais rápido" não podem ser respondidas, nem mesmo dando ordens de magnitude.

Konrad Rudolph
fonte
177
Você tem alguma evidência para apoiar sua ultrajante reivindicação de cinco laranjas? Todos os meus experimentos apontam para 2 laranjas, no máximo, com uma melhoria de 3 mangas ao realizar a metaprogramação de modelos.
Alex
42
No fermento, ele não está clamando por hors d'oeuvres de magnitude mais rápido.
Chris
11
Da minha experiência é bastante 5,2 laranjas. Mas isso depende do medidor de fruta que você usa.
Dio F
4
Update, em si StackOverflow desarrumada e alças comenta ineficientes, assim, menos bananas (300 bananas pior do que deveria ser): meta.stackexchange.com/questions/254534/...
KeksArmee
87

Começarei discordando de parte da resposta aceita (e bem votada) a esta pergunta, afirmando:

Na verdade, existem várias razões pelas quais o código JITted será executado mais lentamente que um programa C ++ (ou outro idioma sem sobrecarga de tempo de execução) otimizado corretamente, incluindo:

  • os ciclos de computação gastos no código JITting em tempo de execução são, por definição, indisponíveis para uso na execução do programa.

  • quaisquer caminhos ativos no JITter estarão competindo com seu código por instruções e cache de dados na CPU. Sabemos que o cache domina quando se trata de desempenho e idiomas nativos como C ++ não têm esse tipo de disputa, por definição.

  • o orçamento de tempo de um otimizador de tempo de execução é necessariamente muito mais restrito do que o de um otimizador de tempo de compilação (como outro comentarista apontou)

Bottom line: Finalmente, você irá quase certamente ser capaz de criar uma implementação mais rápida em C ++ do que você poderia, em C # .

Agora, com isso dito, o quão mais rápido realmente não é quantificável, pois há muitas variáveis: tarefa, domínio do problema, hardware, qualidade das implementações e muitos outros fatores. Você executará testes no seu cenário para determinar a diferença de desempenho e depois decidir se vale a pena o esforço e a complexidade adicionais.

Este é um tópico muito longo e complexo, mas acho que vale a pena mencionar por uma questão de integridade que o otimizador de tempo de execução do C # é excelente e é capaz de executar certas otimizações dinâmicas em tempo de execução que simplesmente não estão disponíveis para o C ++ com seu tempo de compilação ( estático) otimizador. Mesmo com isso, a vantagem ainda é tipicamente profunda no tribunal do aplicativo nativo, mas o otimizador dinâmico é a razão do " quase qualificador certamente" fornecido acima.

-

Em termos de desempenho relativo, também fiquei perturbado com os números e discussões que vi em outras respostas, por isso pensei em dar um toque e, ao mesmo tempo, fornecer algum suporte para as declarações que fiz acima.

Uma grande parte do problema com esses benchmarks é que você não pode escrever código C ++ como se estivesse escrevendo C # e espera obter resultados representativos (por exemplo, executar milhares de alocações de memória em C ++ dará números terríveis).

Em vez disso, escrevi um código C ++ um pouco mais idiomático e comparei com o código C # @Wiory fornecido. As duas principais alterações que fiz no código C ++ foram:

1) vetor usado :: reserve ()

2) achatou a matriz 2d para 1d para alcançar melhor localidade do cache (bloco contíguo)

C # (.NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

Tempo de execução (versão): Init: 124ms, Fill: 165ms

C ++ 14 (Clang v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

Tempo de execução (versão): Init: 398µs (sim, isso é microssegundos), Fill: 152ms

Tempo total de execução: C #: 289ms, C ++ 152ms (aproximadamente 90% mais rápido)

Observações

  • Alterar a implementação do C # para a mesma implementação da matriz 1d resultou em Init: 40ms, Fill: 171ms, Total: 211ms (o C ++ ainda era quase 40% mais rápido ).

  • É muito mais difícil projetar e escrever código "rápido" em C ++ do que escrever código "regular" em qualquer idioma.

  • É (talvez) incrivelmente fácil obter um desempenho ruim em C ++; vimos isso com desempenho de vetores não reservados. E há muitas armadilhas como essa.

  • O desempenho do C # é bastante surpreendente quando você considera tudo o que está acontecendo no tempo de execução. E esse desempenho é comparativamente fácil de acessar.

  • Mais dados anedóticos comparando o desempenho de C ++ e C #: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

A conclusão é que o C ++ oferece muito mais controle sobre o desempenho. Deseja usar um ponteiro? Uma referência? Pilha de memória? Montão? Polimorfismo dinâmico ou eliminar a sobrecarga de tempo de execução de uma tabela com polimorfismo estático (via templates / CRTP)? Em C ++, você precisa ... er, chegar a fazer todas essas escolhas (e mais) você mesmo, idealmente, para que sua solução resolva melhor o problema que você está enfrentando.

Pergunte a si mesmo se você realmente deseja ou precisa desse controle, porque mesmo para o exemplo trivial acima, você pode ver que, embora haja uma melhoria significativa no desempenho, é necessário um investimento mais profundo para acessar.

U007D
fonte
16
@Quonux obrigado pelo comentário. Claro que este não é um "programa real". O ponto dos benchmarks foi refatorar um benchmark C # oferecido em outras partes desta página como evidência de que o código JIT é de alguma forma mais rápido que o nativo - não é, e o benchmark era potencialmente enganador para novas pessoas.
U007D
9
@Quonux, por que você tem que escrever assim? São pessoas como você que me fazem não gostar do stackoverflow.
Markus Knappen Johansson
5
@MarkusKnappenJohansson Eu tive um dia ruim;), eu também sou humano, removi meu voto negativo, mas minha opinião ainda se aplica. Oh, por favor, não goste de SO, apenas porque existem pessoas "estúpidas" :). Tenha uma boa.
Quonux 22/07
9
MARCA COMPLETAMENTE ENGANOSA. Na versão C ++, você está simplesmente reservando parte da memória (e depois se perguntando como essa operação leva microssegundos para executar). Na versão C #, você está criando 5000 ARRAYS (instanciando objetos na memória). O C ++ é mais rápido que o C # ... mas a diferença não chega nem perto dos 40% ... no momento, está mais na faixa de <10%. O que seu exemplo ilustra é que os programadores devem seguir a linguagem de sua escolha (e do seu perfil é óbvio que você é programador de carreira em C ++). Em C # você pode fazer um array 2D int[,]... seguindo com o exemplo.
Nikib3ro
3
Pelo que sei, o código no seu exemplo de C ++ está literalmente alocando a memória antes do tempo. A implementação PROPER C # simplesmente escreveria 'List <double> arrs = new List <double> (ROWS * COLS)', que aloca a memória necessária para indexar uma matriz bidimensional em um formato dimensional (por exemplo, o que você fez em C ++). Não há absolutamente nenhuma razão para alocar uma matriz bidimensional e achatá-la manualmente - a enorme quantidade de iterações no pré-teste é a causa do desempenho de merda. Eu imagino que a sobrecarga ainda seria maior em C #, mas não em uma quantidade considerável.
JDweetBeat #
62

Na minha experiência (e trabalhei muito com as duas linguagens), o principal problema com o C # comparado ao C ++ é o alto consumo de memória e não encontrei uma boa maneira de controlá-lo. Foi o consumo de memória que eventualmente desacelerou o software .NET.

Outro fator é que o compilador JIT não pode gastar muito tempo para fazer otimizações avançadas, porque é executado em tempo de execução, e o usuário final notaria se demorasse muito tempo. Por outro lado, um compilador C ++ tem todo o tempo necessário para fazer otimizações em tempo de compilação. Esse fator é muito menos significativo que o consumo de memória, IMHO.

Nemanja Trifunovic
fonte
6
Em um projeto em andamento, tivemos que extrair enormes quantidades de dados, incluindo manter muitos GB na memória simultaneamente e realizar cálculos caros em todos eles - isso exigiu controle preciso de todas as alocações, C ++ era praticamente a única opção. +1 para C ++. Por outro lado, esse era apenas um projeto, passamos a maior parte do tempo escrevendo sistemas que interagiam com simuladores lentos, e a depuração poderia ser um pesadelo, então eu gostaria de poder usar uma linguagem de otimização de tempo do programador para todas as outras. coisa.
Bogatyr
7
@IngeHenriksen: Conheço bem o padrão Dispose, mas não ajuda em nada com a memória gerenciada.
Nemanja Trifunovic
10
A disposição do @IngeHenriksen garante apenas que o método Dispose foi chamado. O descarte nunca libera a memória coletada do lixo. O método Dispose destina-se apenas à limpeza de recursos não gerenciados, como identificadores de arquivo, e não tem nada a ver com o gerenciamento de memória.
precisa saber é o seguinte
1
@NemanjaTrifunovic: "O compilador JIT não pode gastar muito tempo para fazer otimizações avançadas". Você pode citar algumas otimizações que não são feitas pelos JITs, porque levariam muito tempo?
quer
5
@ user3800527: Mesmo que a adição de RAM sempre tenha sido possível (e não é - imagine a Microsoft adicionando RAM a cada usuário do MS Office), isso não resolverá o problema. A memória é hierárquica e um programa C # terá muito mais erros de cache do que um C ++.
Nemanja Trifunovic
35

Um cenário específico em que o C ++ ainda tem vantagem (e, nos próximos anos) ocorre quando decisões polimórficas podem ser predeterminadas em tempo de compilação.

Geralmente, o encapsulamento e a tomada de decisões adiada são uma coisa boa, pois tornam o código mais dinâmico, mais fácil de se adaptar às mudanças nos requisitos e mais fácil de usar como estrutura. É por isso que a programação orientada a objetos em C # é muito produtiva e pode ser generalizada sob o termo "generalização". Infelizmente, esse tipo específico de generalização tem um custo em tempo de execução.

Geralmente, esse custo não é substancial, mas há aplicativos em que a sobrecarga de chamadas de métodos virtuais e a criação de objetos podem fazer a diferença (especialmente porque os métodos virtuais impedem outras otimizações, como o embutimento de chamadas de métodos). É aqui que o C ++ tem uma enorme vantagem, pois é possível usar modelos para obter um tipo diferente de generalização que não afeta o tempo de execução, mas não é necessariamente menos polimórfico que o OOP. De fato, todos os mecanismos que constituem OOP podem ser modelados usando apenas técnicas de modelo e resolução em tempo de compilação.

Nesses casos (e reconhecidamente, eles geralmente são restritos a domínios de problemas especiais), o C ++ vence o C # e linguagens comparáveis.

Konrad Rudolph
fonte
6
Na verdade, as Java VMs (e provavelmente .NET) se esforçam muito para evitar o envio dinâmico. Basicamente, se houver uma maneira de evitar polimorfismos, você pode ter certeza de que sua VM fará isso.
267 Martin Probst
3
Sempre tenho problemas para explicar isso aos meus colegas de C # que conhecem pouco C ++ de uma maneira que lhes permita apreciar o significado. Você explicou isso muito bem.
Roman Starkov
9
@cracy: você está fazendo sua aposta sem aplicativos de computação de alto desempenho. Considere previsão do tempo, bioinformática e simulações numéricas. O líder de desempenho do C ++ nessas áreas não diminui, porque nenhum outro código pode obter desempenho comparável no mesmo nível de alta abstração.
Konrad Rudolph
5
@ Jon Maçãs e laranjas. Sua afirmação específica era "C # é ordens de magnitude mais rápidas que C ++ no contexto de metaprogramação", não "usar código pré-compilado é ordens de magnitude mais rápido que código interpretado". Enquanto estamos nisso, sua afirmação de que a geração de código em tempo de execução é "mais geral" do que a geração de código em tempo de compilação também está claramente errada - ambos têm pontos fortes e fracos. A geração de código em tempo de compilação usa o sistema de tipos para fornecer segurança de tipo estático - a geração de código de tempo de execução não pode fazer isso ( pode fornecer segurança de tipo forte, mas não de tipo estático ).
Konrad Rudolph
5
@ user3800527 Acho que você está perdendo o ponto principal desta resposta. É claro que você pode contornar isso quebrando o encapsulamento e caindo em estruturas de baixo nível - você pode escrever o assembly em (quase) qualquer idioma. O que torna o C ++ (quase) único e adequado exclusivamente para a programação de alto desempenho é que você pode criar abstrações de alto nível sem custo de tempo de execução. Portanto, você não precisa escrever código do tipo assembly em C ++ para obter um desempenho premium: um bem escrito sort(arr, generic_comparer)será tão eficiente quanto um loop escrito à mão no C ++. Nunca será em c #.
Konrad Rudolph
20

C ++ (ou C) fornece controle refinado sobre suas estruturas de dados. Se você quiser mexer um pouco, você tem essa opção. Aplicativos Java ou .NET gerenciados grandes (OWB, Visual Studio 2005 ) que usam as estruturas de dados internas das bibliotecas Java / .NET carregam a bagagem com eles. Eu já vi sessões de designer OWB usando mais de 400 MB de RAM e BIDS para design de cubo ou ETL entrando nos 100's de MB também.

Em uma carga de trabalho previsível (como a maioria dos benchmarks que repetem um processo várias vezes), um JIT pode obter um código otimizado o suficiente para que não haja diferença prática.

Na IMO, em aplicativos grandes, a diferença não é tanto o JIT quanto as estruturas de dados que o próprio código está usando. Nos casos em que um aplicativo possui muita memória, você obtém um uso de cache menos eficiente. As falhas de cache nas CPUs modernas são bastante caras. Onde C ou C ++ realmente vencem é onde você pode otimizar o uso de estruturas de dados para jogar bem com o cache da CPU.

ConcernedOfTunbridgeWells
fonte
19

Para gráficos, a classe C # Graphics padrão é bem mais lenta que a GDI acessada via C / C ++. Eu sei que isso não tem nada a ver com o idioma em si, mais com a plataforma .NET total, mas o Graphics é o que é oferecido ao desenvolvedor como um substituto do GDI, e seu desempenho é tão ruim que eu nem ousaria fazer gráficos com isso.

Temos uma referência simples que usamos para ver a rapidez com que uma biblioteca de gráficos é, e isso é simplesmente desenhar linhas aleatórias em uma janela. O C ++ / GDI ainda é rápido com 10.000 linhas, enquanto o C # / Graphics tem dificuldade em fazer 1000 em tempo real.

QBziZ
fonte
5
Fiquei intrigado com a sua resposta. Você já testou o mesmo benchmark com código inseguro e lockbits e desenhando as linhas aleatórias por conta própria? Agora isso seria uma coisa interessante de se olhar.
Pedery
2
@ Pediatria não, eu não tenho. apenas usando o GDI e o .NET.Graphics da maneira mais básica. o que você quer dizer com "desenhando as linhas aleatórias"?
QBziZ
1
Talvez você deva considerar testar isso para obter métricas mais realistas sobre a velocidade do C #. Aqui está uma boa visão geral da técnica: bobpowell.net/lockingbits.htm #
Pedery
6
Não é isso que queremos fazer, colocando pixels separados em um buffer de quadros. Se você precisa implementar tudo sozinho, qual é o sentido de ter uma API / plataforma para codificar? Para mim, isso não é argumento. Nunca precisamos colocar pixels separados em um buffer de quadro no GDI para desenhar linhas, e também não planejamos fazer isso no .NET. Na minha opinião, usamos uma métrica realista e o .NET acabou sendo lento.
QBziZ
1
Bem, eu tenho apenas uma pequena idéia do que é a detecção de blob, mas apenas declarar uma sincronização não prova nada. Você escreveu um em C ++? Em JavaScript? E comparou aqueles ao c #? Além disso, não acho que a detecção de blob esteja usando muitas primitivas gráficas. Corrija-me se estiver errado, mas acho que são algoritmos estatísticos executando operações em pixels.
QBziZ 17/04
13

A coleta de lixo é o principal motivo pelo qual o Java # NÃO PODE ser usado para sistemas em tempo real.

  1. Quando o GC acontecerá?

  2. Quanto tempo vai demorar?

Isso não é determinístico.


fonte
5
Eu não sou um grande fã de Java, mas não há nada que diga que o Java não pode usar um GC amigável em tempo real.
Zan Lynx
5
Existem muitas implementações de GC em tempo real, se você quiser dar uma olhada. (GC é uma área que está transbordando com trabalhos de pesquisa)
Arafangion
Na FWIW, Richard Jones acaba de publicar uma versão atualizada de seu livro de coleta de lixo, que abrange, entre outras coisas, projetos de GC em tempo real de ponta.
Jon Harrop
11
Este é um argumento sem sentido, Windows (e Linux) não são sistemas operacionais em tempo real. Seu código C ++ também pode ser trocado por um número de slots de 18 ms a qualquer momento.
Henk Holterman
2
@HenkHolterman True, mas você sempre pode escrever um carregador de inicialização em montagem, amarrá-lo em uma inicialização de kernel para seu aplicativo e executar seus aplicativos C ++ diretamente no hardware (em RT btw). Você não pode fazer isso em C # e qualquer esforço que eu tenha visto apenas imita o assembly pré-compilado em C # e usa uma tonelada de código C, o que torna inútil usar C #. Ler tudo isso é meio engraçado, porque o C # é realmente inútil sem o .NET framework.
zackery.fix
11

Tivemos que determinar se o C # era comparável ao C ++ no desempenho e escrevi alguns programas de teste para isso (usando o Visual Studio 2005 para os dois idiomas). Aconteceu que, sem coleta de lixo e considerando apenas a linguagem (não a estrutura), o C # tem basicamente o mesmo desempenho que o C ++. A alocação de memória é muito mais rápida em C # do que em C ++ e o C # tem uma ligeira vantagem no determinismo quando os tamanhos de dados são aumentados além dos limites da linha de cache. No entanto, tudo isso acabou sendo pago e há um custo enorme na forma de acertos não determinísticos de desempenho para C # devido à coleta de lixo.

ILoveFortran
fonte
1
No C ++, você tem a opção de usar diferentes métodos de alocação; portanto, dependendo de como a memória foi alocada (AOT?) Em C #, isso pode ser feito da mesma maneira (mas muito mais rápido) em C ++.
Zackery.fix 12/01/16
5
@ zackery.fix O .NET tem uma vantagem interessante na alocação de heap, porque só precisa mover um ponteiro para alocar um novo objeto. Isso só é possível devido ao compactador de lixo. Claro que você pode fazer o mesmo em C ++, mas o C ++ não faz isso. É engraçado como você usar o mesmo argumento para dizer "C # podia, mas não, por isso é lixo" e "C ++ não faz, mas o que podia, por isso é incrível" :)
Luaan
9

Como de costume, isso depende da aplicação. Há casos em que o C # é provavelmente insignificante mais lento e outros em que o C ++ é 5 ou 10 vezes mais rápido, especialmente nos casos em que as operações podem ser facilmente executadas no SIMD.

Dark Shikari
fonte
O melhor caso para VMs será a compilação em tempo de execução do código gerado (por exemplo, para corresponder a uma expressão regular lida em tempo de execução) porque os programas C ++ vanilla compilados estaticamente podem usar apenas interpretação porque não possuem um compilador JIT embutido.
Jon Harrop
Nota do futuro: o .NET tem suporte para SIMD e amigos desde 2014, embora não seja amplamente usado.
Luaan 14/07/16
9

Eu sei que não é o que você estava perguntando, mas o C # geralmente é mais rápido de escrever do que o C ++, que é um grande bônus em um ambiente comercial.

Kramii
fonte
2
Eu diria que é mais rápido na maioria das vezes :)
Armadilha
8

O C / C ++ pode ter um desempenho muito melhor em programas em que existem matrizes grandes ou loop / iteração pesada sobre matrizes (de qualquer tamanho). Esse é o motivo pelo qual os gráficos geralmente são muito mais rápidos em C / C ++, porque operações pesadas de matriz estão subjacentes a quase todas as operações gráficas. O .NET é notoriamente lento nas operações de indexação de matriz devido a todas as verificações de segurança, e isso é especialmente verdadeiro para matrizes multidimensionais (e, sim, matrizes C # retangulares são ainda mais lentas que matrizes C # irregulares).

Os bônus do C / C ++ são mais pronunciados se você ficar diretamente com os ponteiros e evitar o Boost std::vectore outros contêineres de alto nível, bem como inlinetodas as pequenas funções possíveis. Use matrizes da velha escola sempre que possível. Sim, você precisará de mais linhas de código para realizar o mesmo que fez em Java ou C #, pois evita contêineres de alto nível. Se você precisar de uma matriz de tamanho dinâmico, lembre-se de emparelhá-la new T[]com uma delete[]instrução correspondente (ou usestd::unique_ptr) - o preço da velocidade extra é que você deve codificar com mais cuidado. Mas, em troca, você se livra da sobrecarga do coletor de memória / lixo gerenciado, que pode ser facilmente 20% ou mais do tempo de execução de programas fortemente orientados a objetos em Java e .NET, bem como daqueles maciços gerenciados custos de indexação da matriz de memória. Os aplicativos C ++ também podem se beneficiar de algumas opções bacanas do compilador em certos casos específicos.

Sou um programador especialista em C, C ++, Java e C #. Recentemente, tive a rara ocasião de implementar exatamente o mesmo programa algorítmico nas três últimas línguas. O programa tinha muitas operações matemáticas e de matriz multidimensional. Eu otimizei bastante isso nos três idiomas. Os resultados foram típicos do que normalmente vejo em comparações menos rigorosas: o Java foi cerca de 1,3x mais rápido que o C # (a maioria das JVMs é mais otimizada que o CLR), e a versão do ponteiro bruto do C ++ veio cerca de 2,1x mais rápido que o C #. Observe que o programa C # usava apenas código seguro - é minha opinião que você também deve codificá-lo em C ++ antes de usar a unsafepalavra - chave.

Para que ninguém pense que eu tenho algo contra o C #, terminarei dizendo que o C # é provavelmente o meu idioma favorito. É a linguagem de desenvolvimento mais lógica, intuitiva e rápida que encontrei até agora. Eu faço toda a minha prototipagem em c #. A linguagem C # tem muitas vantagens pequenas e sutis sobre o Java (sim, eu sei que a Microsoft teve a chance de corrigir muitas das deficiências do Java entrando no jogo tarde e copiando o Java). Brindar a Calendarclasse de Java alguém? Se a Microsoft envidar algum esforço real para otimizar o CLR e o .NET JITter, o C # poderá assumir seriamente. Sinceramente, estou surpreso que eles ainda não tenham feito - eles fizeram tantas coisas certas na linguagem C #, por que não seguir com otimizações de compiladores de alto impacto? Talvez se todos nós implorarmos.

Molho Especial
fonte
3
"você só precisa lembrar de emparelhar o seu new T[]com um correspondente delete[]" - Não, você não. Tem std::unique_ptrque fazer isso por você.
emlai
supondo que você tenha escrito algo em gráficos, por que escrever código seguro em c #, já pensou em usar código não seguro e comparar novamente?
user3800527
7

> Pelo que ouvi ...

Sua dificuldade parece estar em decidir se o que você ouviu é credível, e essa dificuldade será repetida apenas quando você tentar avaliar as respostas neste site.

Como você vai decidir se as coisas que as pessoas dizem aqui são mais ou menos credíveis do que o que você ouviu originalmente?

Uma maneira seria pedir evidências .

Quando alguém afirma "há algumas áreas em que o C # prova ser mais rápido que o C ++", pergunte por que eles dizem isso , peça que lhe mostrem as medidas, peça que mostre os programas. Às vezes eles simplesmente cometeram um erro. Às vezes, você descobrirá que eles estão apenas expressando uma opinião em vez de compartilhar algo que eles podem mostrar que é verdade.

Muitas vezes, informações e opiniões se misturam no que as pessoas afirmam, e você terá que tentar descobrir qual é qual. Por exemplo, das respostas neste fórum:

  • "Considere os benchmarks em http://shootout.alioth.debian.org/ com muito ceticismo, pois esses testes testam amplamente o código aritmético, que provavelmente não é nem um pouco parecido com o seu código".

    Pergunte a si mesmo se você realmente entende o que "esses códigos aritméticos de teste em grande parte" significam e, em seguida, pergunte a si mesmo se o autor realmente mostrou a você que sua afirmação é verdadeira.

  • "Esse é um teste bastante inútil, pois realmente depende de quão bem os programas individuais foram otimizados; eu consegui acelerar alguns deles em 4-6 vezes ou mais, deixando claro que a comparação entre programas não otimizados é bastante boba."

    Pergunte a si mesmo se o autor realmente mostrou a você que ele conseguiu "acelerar alguns deles de 4 a 6 vezes ou mais" - é uma afirmação fácil de fazer!

Peter Mortensen
fonte
Não concordo mais com você e foi por isso que perguntei neste fórum ... Afinal, as respostas precisam estar em algum lugar, não é? :)
Armadilha
1
Sim. A resposta é "Depende".
user49117
6

Para problemas 'embaraçosamente paralelos', ao usar o Intel TBB e o OpenMP no C ++, observei um aumento de desempenho de aproximadamente 10 vezes em comparação com problemas semelhantes (matemática pura) feitos com C # e TPL. O SIMD é uma área em que o C # não pode competir, mas também tive a impressão de que o TPL tem uma sobrecarga considerável.

Dito isso, só uso C ++ para tarefas críticas de desempenho, onde sei que poderei multithread e obter resultados rapidamente. Para todo o resto, C # (e ocasionalmente F #) está bem.

Dmitri Nesteruk
fonte
5

É uma pergunta extremamente vaga, sem respostas definitivas reais.

Por exemplo; Prefiro jogar jogos em 3D criados em C ++ do que em C #, porque o desempenho é certamente muito melhor. (E eu sei XNA, etc., mas não chega nem perto da coisa real).

Por outro lado, como mencionado anteriormente; você deve desenvolver em uma linguagem que permita fazer o que deseja rapidamente e, se necessário, otimizar.

David The Man
fonte
4
Você poderia citar alguns exemplos? Jogos escritos em C # o que você encontrou lento
Karl
1
Até os aplicativos de exemplo que vieram com a instalação pareciam lentos.
David The Man
9
O coletor de lixo é uma grande responsabilidade na criação de jogos com C #, pois pode funcionar a qualquer momento, causando grandes pausas. O gerenciamento explícito de memória acaba sendo mais fácil para o desenvolvimento de jogos.
postfuturist
3
Os jogos mais modernos são limitados por GPU. Para esses jogos, não importa se a lógica (executada na CPU) é 10% mais lenta, eles ainda estão limitados pela GPU, não pela CPU. O coletor de lixo é um problema real, causando congelamentos curtos aleatórios se as alocações de memória não forem ajustadas corretamente.
Michael Entin
2
@postfuturist: Isso não é verdade no PC; o coletor de lixo faz um bom trabalho ao entrar e sair, nunca tive problemas com ele. No entanto, no XBox 360 e Zune / Windows-7-Phone, o coletor de lixo não é quase tão inteligente como no PC; Também nunca escrevi para eles, mas as pessoas que me dizem que o coletor de lixo é um grande problema.
BlueRaja - Danny Pflughoeft
5

As linguagens .NET podem ser tão rápidas quanto o código C ++ ou ainda mais rápidas, mas o código C ++ terá uma taxa de transferência mais constante, pois o tempo de execução do .NET precisa pausar para o GC , mesmo que seja muito inteligente sobre suas pausas.

Portanto, se você tiver algum código que precise ser executado rapidamente de forma consistente e sem pausa, o .NET apresentará latência em algum momento , mesmo se você for muito cuidadoso com o GC de tempo de execução.

Florian Doyon
fonte
6
-1: Este é realmente um mito. Em primeiro lugar, a latência do C ++ idiomático é realmente terrível e muitas vezes muito pior que o .NET, porque o RAII causa avalanches de destruidores quando grandes estruturas de dados ficam fora do escopo, enquanto os GCs modernos são incrementais e o .NET é ainda simultâneo. Em segundo lugar, você pode remover completamente as pausas do GC no .NET não alocando.
Jon Harrop
2
Se você fizer isso, precisará renunciar ao uso da BCL, pois a maioria dos métodos cria objetos transitórios.
Florian Doyon
5
Isso é verdade, não foi até o .net 4 que o GC foi incrementado. Temos um aplicativo C # grande que faz uma pausa de segundos por vez no GC. Para aplicativos críticos para o desempenho, isso é um assassino.
11117 Justin
5
Há uma razão pela qual os programas que tendem a empurrar o hardware tendem a usar C ++. Você tem um controle mais preciso quando precisa. O desempenho é fundamental apenas quando você está pressionando o sistema; caso contrário, use C # ou Java para economizar seu tempo.
VoronoiPotato
4
se você não pode gerenciar o comportamento do cache, não consegue vencer o código c ++ otimizado. Uma falta de cache do L1 na memória principal pode atrasar sua operação 100 vezes.
DAG
4

Em teoria, para aplicativos de servidor de longa execução, uma linguagem compilada por JIT pode se tornar muito mais rápida do que uma contraparte compilada nativamente. Como a linguagem compilada JIT geralmente é compilada primeiro em uma linguagem intermediária de nível bastante baixo, é possível realizar muitas otimizações de alto nível no momento da compilação. A grande vantagem é que o JIT pode continuar recompilando seções de código rapidamente, à medida que obtém mais e mais dados sobre como o aplicativo está sendo usado. Ele pode organizar os caminhos de código mais comuns para permitir que a previsão de ramificação seja bem-sucedida o mais rápido possível. Ele pode reorganizar blocos de código separados que são frequentemente reunidos para mantê-los no cache. Ele pode gastar mais esforço para otimizar loops internos.

Duvido que isso seja feito pelo .NET ou por qualquer um dos JREs, mas estava sendo pesquisado quando eu estava na universidade, por isso não é razoável pensar que esse tipo de coisa possa chegar ao mundo real em algum momento em breve .

Eclipse
fonte
4

Aplicativos que requerem acesso intensivo à memória, por exemplo. a manipulação de imagens geralmente é melhor gravada em ambiente não gerenciado (C ++) do que gerenciada (C #). Loops internos otimizados com aritmética de ponteiro são muito mais fáceis de controlar no C ++. Em C #, pode ser necessário recorrer a códigos não seguros para se aproximar do mesmo desempenho.

Kalle
fonte
4

Eu testei vectorem C ++ e C # equivalente - Liste matrizes 2D simples.

Estou usando as edições do Visual C # / C ++ 2010 Express. Ambos os projetos são simples aplicativos de console, eu os testei no modo de liberação e depuração padrão (sem configurações personalizadas). Listas de C # rodam mais rápido no meu pc, inicialização de array também é mais rápida em C #, operações matemáticas são mais lentas.

Estou usando o Intel Core2Duo [email protected], C # - .NET 4.0.

Eu sei que a implementação do vetor é diferente da lista C #, mas eu só queria testar as coleções que eu usaria para armazenar meus objetos (e poder usar o acessador de índice).

Claro que você precisa limpar a memória (digamos para todos os usos new), mas eu queria manter o código simples.

Teste vetorial C ++ :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

Teste de lista de C #:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

Matriz C ++:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

Matriz:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

Hora: (Lançamento / Depuração)

C ++

  • 600/606 ms array init,
  • Preenchimento de matriz de 200/270 ms,
  • 1seg / 13seg vetor init & fill.

(Sim, 13 segundos, sempre tenho problemas com listas / vetores no modo de depuração.)

C #:

  • Init de matriz de 20/20 ms,
  • Preenchimento de matriz 403/440 ms,
  • 710/742 ms list init & fill.
Wiory
fonte
1
Eu adoraria ver o acessador de índice em std :: list. De qualquer forma, leva 37 segundos com a lista, modo de lançamento. Liberar sem depuração: lista 3s, vetor 0,3 s. Provavelmente não referenciando problema ou sth. Exemplo: nopaste.pl/12fb
Wiory 23/06
2
Para medições mais precisas, você não deve usar System.DateTime.Now, mas a classe Stopwatch .
Sam
4
Parte do motivo pelo qual você está obtendo tempos de preenchimento lentos para o vetor em C ++ é que você está usando push_back. Isso demonstrou em várias postagens ser mais lento do que usar o método at ou o operador []. Para usar um desses métodos, você precisa usar o método de redimensionamento ou reserva. Além disso, o motivo pelo qual sua inicialização está demorando tanto para o caso do vetor c ++ é que você está forçando um operador de cópia ou atribuição [não tenho certeza qual nesse caso) a inicializar o vetor c ++. Para a matriz em c ++, existe um algoritmo que usa 2 novas chamadas em vez de 5001 e é mais rápido também.
Zachary Kraus
5
Eu acho que você não fez c ++ de maneira apropriada. Apenas uma olhada e encontrei muitos problemas. Exemplo: vector <vector <double>> myList = vector <vector <double>> ()
DAG
2
Uau. Não tenho certeza de quais conclusões podemos tirar da comparação de Listas e matrizes redimensionáveis, mas se você usar vetores como esse, precisará aprender sobre reserve (), meu amigo, reserve ().
U007D
3

Bem, isto depende. Se o código de byte for traduzido em código de máquina (e não apenas JIT) (quero dizer, se você executar o programa) e se o seu programa usar muitas alocações / desalocações, poderá ser mais rápido, porque o algoritmo GC precisa apenas de uma passagem (teoricamente) por toda a memória uma vez, mas chamadas normais malloc / realloc / free C / C ++ causam uma sobrecarga em todas as chamadas (sobrecarga de chamada, sobrecarga de estrutura de dados, falta de cache;)).

Por isso, é teoricamente possível (também para outras línguas do GC).

Eu realmente não vejo a extrema desvantagem de não poder usar a metaprogramação com C # para a maioria dos aplicativos, porque a maioria dos programadores não a usa de qualquer maneira.

Outra grande vantagem é que o SQL, como a "extensão" do LINQ , oferece oportunidades para o compilador otimizar chamadas para bancos de dados (em outras palavras, o compilador pode compilar o LINQ inteiro em um binário de "blob" onde as funções chamadas são incorporadas ou para seu uso otimizado, mas estou especulando aqui).

Quonux
fonte
1
Qualquer desenvolvedor C ++ adequado não terá os problemas que você descreve. Somente programadores C ruins que decidiram colocar aulas em seus programas e chamá-lo de C ++ têm esses problemas.
clara
1
para o amor dos deuses, este é de 8 anos, OMFGz
Quonux
fique à vontade para dar uma melhor mais atualizado resposta
Quonux
2

Suponho que existem aplicativos escritos em C # executando rapidamente, assim como existem mais aplicativos escritos em C ++ executando rapidamente (bem, C ++ é um pouco mais antigo ... e também leva o UNIX ...)
- a questão é: o que é isso, usuários e os desenvolvedores estão reclamando ...
Bem, IMHO, no caso de C #, temos uma interface muito confortável, uma hierarquia muito boa de bibliotecas e todo o sistema de interface da CLI. No caso de C ++, temos modelos, ATL, COM, MFC e todo o código já escrito e em execução, como OpenGL, DirectX e assim por diante ... Os desenvolvedores reclamam de chamadas indevidamente aumentadas da GC no caso de C # (significa que o programa é rápido e em um segundo - bang! está preso).
Escrever código em C # de maneira muito simples e rápida (para não esquecer que também aumenta a chance de erros. No caso de C ++, os desenvolvedores reclamam de vazamentos de memória, - significa esmagamentos, chamadas entre DLLs e também "DLL hell" - problema com bibliotecas de suporte e substituição por novas ...
Acho que mais habilidade você terá na linguagem de programação, mais qualidade (e velocidade) caracterizará seu software.

bgee
fonte
2

Eu diria da seguinte maneira: programadores que escrevem código mais rápido são os que estão mais informados sobre o que faz com que as máquinas atuais acelerem e, aliás, também são os que usam uma ferramenta apropriada que permite determinismos precisos e de baixo nível. técnicas de otimização. Por esses motivos, são essas pessoas que usam C / C ++ em vez de C #. Eu iria tão longe quanto afirmar isso como um fato.

Johan Boulé
fonte
O minecraft codificado por Notch é bastante rápido, considerando a quantidade de dados que ele está manipulando. Além disso, ele o codificou principalmente sozinho em um período comparativamente curto de tempo, algo que seria praticamente impossível em C ++. No entanto, concordo com as técnicas de otimização - se você tiver um tempo extra de desenvolvimento de 10x para que seu código seja executado duas vezes mais rápido, provavelmente vale a pena.
Bill K
2

Se não me engano, os modelos C # são determinados em tempo de execução. Isso deve ser mais lento que os modelos de tempo de compilação do C ++.

E quando você realiza todas as outras otimizações em tempo de compilação mencionadas por tantas outras, bem como a falta de segurança que realmente significa mais velocidade ...

Eu diria que o C ++ é a escolha óbvia em termos de velocidade bruta e consumo mínimo de memória. Mas isso também se traduz em mais tempo desenvolvendo o código e garantindo que você não esteja vazando memória ou causando exceções de ponteiro nulo.

Veredito:

  • C #: desenvolvimento mais rápido, execução mais lenta

  • C ++: desenvolvimento lento, execução mais rápida.

HumbleWebDev
fonte
1

Realmente depende do que você está tentando realizar no seu código. Ouvi dizer que é apenas lenda urbana que existe alguma diferença de desempenho entre VB.NET, C # e C ++ gerenciado. No entanto, descobri, pelo menos nas comparações de string, que o C ++ gerenciado supera o C #, o que, por sua vez, supera o VB.NET.

Eu nunca fiz comparações exaustivas em complexidade algorítmica entre as linguagens. Também estou apenas usando as configurações padrão em cada um dos idiomas. No VB.NET, estou usando configurações para exigir a declaração de variáveis, etc. Aqui está o código que estou usando para C ++ gerenciado: (Como você pode ver, esse código é bastante simples). Estou executando o mesmo nos outros idiomas no Visual Studio 2013 com .NET 4.6.2.

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}
Charles Owen
fonte
1

Existem algumas diferenças importantes entre C # e C ++ no aspecto de desempenho:

  • C # é baseado em GC / heap. A alocação e o próprio GC estão sobrecarregados como a não localidade do acesso à memória
  • O otimizador de C ++ tornou-se muito bom ao longo dos anos. Os compiladores JIT não podem atingir o mesmo nível, pois possuem apenas tempo de compilação limitado e não veem o escopo global

Além disso, a competência do programador também desempenha um papel. Eu vi código C ++ ruim, onde as classes eram passadas por valor como argumento em todo o lugar. Você pode realmente piorar o desempenho em C ++ se não souber o que está fazendo.

gast128
fonte
0

> Afinal, as respostas precisam estar em algum lugar, não têm? :)

Umm não.

Como várias respostas observaram, a pergunta está subespecificada de maneira a convidar perguntas em resposta, não respostas. Para tomar apenas uma maneira:

E então quais programas? Qual maquina? Qual SO? Qual conjunto de dados?

Peter Mortensen
fonte
Eu concordo plenamente. Eu me pergunto por que as pessoas esperam uma resposta precisa (63,5%), quando fazem uma pergunta geral. Eu não acho que não haja resposta geral para esse tipo de pergunta.
me chame de Steve
@ callallesteve: Eu sei o que você quer dizer, mas sua última frase deve soar como pregos sobre um quadro de giz para qualquer programador.
Wouter van Nifterick
1
Isso não parece responder à pergunta e lê mais como um comentário ou discurso retórico.
Tas
-13

Inspirado por isso, fiz um teste rápido com 60% das instruções comuns necessárias na maioria dos programas.

Aqui está o código C #:

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

O array de strings e o arraylist são usados ​​propositadamente para incluir essas instruções.

Aqui está o código c ++:

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

O tamanho do arquivo de entrada que usei foi de 40 KB.

E aqui está o resultado -

  • O código C ++ foi executado em 9 segundos.
  • Código C #: 4 segundos !!!

Ah, mas isso foi no Linux ... Com C # rodando em Mono ... E C ++ com g ++.

OK, foi o que obtive no Windows - Visual Studio 2003 :

  • O código C # foi executado em 9 segundos.
  • Código C ++ - horríveis 370 segundos !!!
rks
fonte
7
Você está usando diferentes estruturas de dados e código da biblioteca, embora "370 segundos" indique algo horrível - você não está executando no depurador por acaso, está? Eu suspeito que o desempenho da biblioteca CSV que você está usando é mais interessante do que o desempenho do idioma que você está usando. Eu questionaria o uso de um vetor nesse contexto e quais otimizações você usou. Além disso, é sabido que os iostreams (em particular, o "myfile << * j <<", ";") são muito mais lentos do que outros métodos de gravação no arquivo, para pelo menos algumas implementações comuns.
Arafangion
6
Por fim, você está trabalhando mais na versão C ++. (Por que você está limpando o csvColumn, csvElement e csvLines?)
Arafangion
2
Toda iteração do loop while vai destruir e reconstruir um std :: istream e um std :: vector e uma std :: string. O corpo while sai do escopo a cada iteração, todas as variáveis ​​dentro do escopo while serão destruídas e construídas em cada iteração.
precisa saber é o seguinte
1
pela aparência de ler seu código c ++, você está tentando copiar de um arquivo para outro. Em vez de usar as interações complexas entre fluxos de arquivos, cadeias, vetores e fluxos de cadeias, você poderia ter copiado o fluxo de arquivos de entrada no fluxo de arquivos de saída. Isso economizaria muito tempo e memória.
Zachary Kraus
2
para fazer testes de velocidade, as coisas de memória não chegam ao disco IO, a menos que você teste nos SSDs mais recentes e seja dedicado ao seu aplicativo de desempenho. Como os computadores gravam constantemente no disco, mesmo que você não toque no teclado.
user3800527