На скільки швидше C ++, ніж C #?


246

Або це навпаки?

З того, що я чув, є деякі сфери, в яких C # виявляється швидшим, ніж C ++, але я ніколи не мав сили кинути це перевірити сам.

Думав, що хтось із вас може детально пояснити ці відмінності або вказати мені на потрібне місце для інформації про це.


7
Захищено, щоб не розміщувати більше випадкових орієнтирів. Якщо ви думаєте, що можете зробити свою справу, для цього вам знадобиться 10 представників.
Роберт Харві

2
Як це все-таки не є закритим як думка / аргументація? Хіба я ще не в StackOverflow? (Не пропонуючи близьких, просто цікаво. Я люблю запитання, що викликають впевнені аргументи)
Білл К

1
Це майже суперечливе питання, враховуючи, що ми живемо в епоху, коли ІЛ можна перетворити на CPP та оптимізувати звідти: docs.unity3d.com/Manual/IL2CPP.html
pixelpax

Мова, яка перевіряє доступ до масиву поза діапазоном, ніколи не буде перевершувати мову, яка цього не робить.
Сева Алексєєва

@SevaAlekseyev Це робить не мова, а компілятор. Однією з причин C ++ є те, що швидко (крім очевидних) є те, що компілятори C ++ існують протягом останніх 35 років (якщо не більше). Ніщо не заважає компіляторам C # покращитися з часом. У випадку, про який ви згадуєте, будь ласка, прочитайте цей stackoverflow.com/questions/16713076/…
Пастка

Відповіді:


343

Не існує жодної суворої причини, чому мова на основі байт-коду, як C # або Java, що має JIT, не може бути такою швидкою, як код C ++. Однак код C ++ раніше був значно швидшим, а також сьогодні все ще є у багатьох випадках. В основному це пов'язано з тим, що більш просунуті оптимізації JIT є складними у впровадженні, а справді круті приходять лише зараз.

Тож C ++ швидше, у багатьох випадках. Але це лише частина відповіді. Випадки, коли C ++ насправді швидший, - це високооптимізовані програми, де експертні програмісти ретельно оптимізували кодовий код. Це не тільки дуже забирає багато часу (і, таким чином, дорого), але також часто призводить до помилок через надмірну оптимізацію.

З іншого боку, код на інтерпретованих мовах стає швидшим у пізніших версіях виконання (.NET CLR або Java VM), не роблячи нічого. І є безліч корисних оптимізацій компіляторів JIT, які просто неможливі для мов з покажчиками. Також дехто стверджує, що збирання сміття, як правило, має бути настільки ж швидким або швидшим, як керування ручною пам’яттю, і в багатьох випадках це. Як правило, все це можна реалізувати на C ++ або C, але це буде набагато складніше і схильним до помилок.

Як сказав Дональд Кнут, "передчасна оптимізація - корінь усього зла". Якщо ви точно знаєте, що ваша програма в основному буде складатися з критичної арифметики з високою ефективністю, і це буде вузьким місцем, і, звичайно, буде швидше в C ++, і ви впевнені, що C ++ не буде конфліктувати з вашим іншим вимоги, перейдіть на C ++. У будь-якому іншому випадку зосередьтеся на тому, щоб спочатку правильно застосувати заявку на будь-якій мові, яка вам найбільше підходить, а потім знайдіть вузькі місця, якщо вона працює занадто повільно, а потім подумайте, як оптимізувати код. У гіршому випадку вам може знадобитися зателефонувати на код C через інтерфейс зовнішньої функції, тому ви все одно матимете можливість писати критичні частини мовою нижчого рівня.

Майте на увазі, що оптимізувати правильну програму порівняно просто, але виправити оптимізовану програму набагато складніше.

Надання фактичних відсотків переваг швидкості неможливо, це багато в чому залежить від вашого коду. У багатьох випадках реалізація мови програмування навіть не є вузьким місцем. Візьміть орієнтири на http://benchmarksgame.alioth.debian.org/ з великою скептичністю, оскільки вони значною мірою перевіряють арифметичний код, який, швидше за все, зовсім не схожий на ваш код.


92
<quote> код на інтерпретованих мовах стає швидшим у пізніших версіях часу виконання </quote> Оскільки код, складений кращою версією компілятора, також стане швидшим.
Мартін Йорк,

47
Насправді є хоча б одна причина: JIT повинен бути швидким і не може дозволити собі витратити час на різні розширені оптимізації, доступні компілятору C ++.
Неманья Трифунович

63
"але також часто призводить до помилок через надмірну оптимізацію." [цитування відчайдушно потрібне]. Я працюю в національній лабораторії, і ми оптимізуємо пекло з коду. Це зазвичай не призводить до помилок коду.
Тодд Гамблін

35
"Оптимізувати правильну програму порівняно просто, але набагато складніше виправити оптимізовану програму."
градбот

20
Інге: не впевнена, що ти на правильному шляху. Так, C # реалізований на іншій мові, але компілятор JIT генерує машинний код, тому це не інтерпретована мова. Таким чином, це не обмежується його реалізацією на C ++. Я не впевнений, чому ви думаєте, що додавання якогось менеджера до чогось по суті робить його швидшим.
Мартін Пробст

202

C # може не бути швидшим, але це робить ВАС / МЕ швидше. Це найважливіший захід для того, що я роблю. :)


68
Ха-ха, є хороша цитата Ларрі Уолла на цю тему. Він говорить про perl, але це може бути продумано для всіх дискусій, що стосуються мов та продуктивності: ".. більш ранні комп'ютерні мови, такі як Fortran і C, були розроблені для ефективного використання дорогого комп'ютерного обладнання. На відміну від цього, Perl призначений для ефективно використовувати дорогих комп'ютерних програмістів "
Фалаїна

60
1. "C # набагато швидше, ніж C ++" 2. "Це не може бути правдою" 1. "Впевнений, що може" 2. "На скільки?" 1. "Зазвичай на 3-4 місяці"
Дмитро С.

2
для C ++ , які на насправді залежить від бібліотеки ви використовуєте, C # не звичайно швидше, .NET є, коли ви говорите продуктивність
Ion Todirel

Це та сама причина, чому ви могли використовувати Python замість C, щоб написати якийсь код ... але, створивши важкі розрахунки, ви можете відчути різницю у продуктивності.
Ч3шир

Це залежать від того, до чого ти звик. Я програмую набагато швидше на C ++, ніж у C #. Знання про бібліотеку є важливою частиною цього, оскільки ви не хочете винаходити колесо для основних завдань. Основною проблемою C / C ++ було управління вказівниками, яке в значній мірі вирішено за допомогою розумних покажчиків. Сказавши, що C ++ серйозно бракує розгалуженої бібліотеки, як пропонує .NET та Java, і це може значною мірою прискорити розвиток. Це не вирішиться найближчим часом, оскільки ті хлопці-стилярі люблять витрачати свій час на вдосконалення шаблонів замість розширень бібліотеки.
gast128

87

Це на п’ять апельсинів швидше. А точніше: не може бути (правильної) бланкетної відповіді. C ++ - це статично складена мова (але тоді також існує оптимізація з керуванням профілем), C # працює за допомогою компілятора JIT. Існує так багато розбіжностей, що на запитання типу "наскільки швидше" не можна відповісти, навіть не наказуючи величини.


177
Чи є у вас які-небудь докази на підтвердження вашої несамовитих претензій на п'ять апельсинів? Усі мої експерименти вказують на 2 апельсини, максимум на 3 манго в процесі метапрограмування шаблонів.
Олексій

42
На дріжджах він не стягує, що швидше закінчуються орди.
Кріс

11
З мого досвіду, це досить 5,2 апельсина. Але це залежить від фруктового метра, який ви використовуєте.
Dio F

4
Оновлення, StackOverflow сам заплутався і обробляє коментарі неефективно, таким чином, менше бананів (на 300 бананів гірше, ніж слід): meta.stackexchange.com/questions/254534/…
KeksArmee

87

Почну з того, що не погоджуюся з частиною прийнятої (і добре підкріпленої) відповіді на це питання, заявивши:

Насправді існує маса причин, чому JITted код буде працювати повільніше, ніж правильно оптимізована програма C ++ (або інша мова без накладних витрат), включаючи:

  • обчислювальні цикли, витрачені на JITting код під час виконання, за визначенням недоступні для використання у виконанні програми.

  • будь-які гарячі шляхи в JITter будуть конкурувати з вашим кодом за інструкціями та кешем даних в процесорі. Ми знаємо, що кеш домінує, коли мова йде про продуктивність, а рідні мови, такі як C ++, не мають такого типу суперечок, за визначенням.

  • Час бюджету оптимізатора часу виконання обов'язково значно обмежений, ніж бюджет оптимізатора часу компіляції (як вказував інший коментатор)

Підсумок: В кінцевому рахунку, ви будете майже напевно буде в змозі створити більш швидку реалізацію в C ++ , ніж ви могли б в C # .

Тепер, маючи на увазі сказане, наскільки швидше насправді неможливо оцінити, оскільки є занадто багато змінних: завдання, проблемний домен, обладнання, якість реалізації та багато інших факторів. Ви будете проводити тести свого сценарію, щоб визначити різницю в продуктивності, а потім вирішите, чи варто додаткового зусилля та складності.

Це дуже довга і складна тема, але я вважаю, що варто згадати заради повноти, що оптимізатор виконання C # є відмінним і здатний виконувати певні динамічні оптимізації під час виконання, які просто недоступні для C ++ за час його компіляції ( статичний) оптимізатор. Навіть при цьому перевага все ще є глибоко в суді нашої програми, але динамічний оптимізатор є причиною " майже класифікатора напевно", наведеного вище.

-

Щодо відносної продуктивності, мене також турбували цифри та дискусії, які я бачив у деяких інших відповідях, тому я думав, що я би задзвонив і, в той же час, надати певну підтримку висловленим вище твердженням.

Величезна частина проблеми з цими орієнтирами полягає в тому, що ви не можете записати код C ++ так, як ніби ви писали C #, і очікуєте отримати репрезентативні результати (наприклад, виконання тисяч розподілу пам'яті в C ++ дасть вам жахливі цифри.)

Натомість я написав трохи більше ідіоматичного коду C ++ і порівняв із наданим кодом C # @Wiory. Дві основні зміни, внесені до коду C ++, були:

1) використаний вектор :: резерв ()

2) розрівняли 2d масив до 1d для досягнення кращої локальності кешу (суміжний блок)

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);
}

Час виконання (реліз): Init: 124ms, Заповнення: 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);
}

Час виконання (реліз): Init: 398 мкс (так, це мікросекунди), заповнення: 152 мс

Загальний час роботи: C #: 289 мс, С ++ 152 мс (приблизно на 90% швидше)

Спостереження

  • Якщо змінити реалізацію C # на ту саму реалізацію 1d масиву, вийшло Init: 40ms, Fill: 171ms, Total: 211ms ( C ++ все ще майже на 40% швидше ).

  • Набагато складніше сконструювати та записати "швидкий" код на C ++, ніж написати "звичайний" код на будь-якій мові.

  • (Можливо) дивно легко отримати низьку продуктивність в C ++; ми це бачили з беззастережною продуктивністю векторів. І є безліч таких підводних каменів.

  • Продуктивність C # досить дивовижна, якщо врахувати все, що відбувається під час виконання. І до цієї продуктивності порівняно легко дістатися.

  • Більше анекдотичних даних, що порівнюють ефективність C ++ та C #: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

Суть полягає в тому, що C ++ дає вам набагато більше контролю над роботою. Ви хочете використовувати вказівник? Довідка? Стек пам'яті? Купи? Динамічний поліморфізм чи усунення накладних витрат вітла зі статичним поліморфізмом (за допомогою шаблонів / CRTP)? У C ++ ви повинні ... ер, дістатися зробити всі ці вибори (і більше) самостійно, в ідеалі , так що ваші рішення кращих адреси проблема , яку ви Tackling.

Запитайте себе, чи дійсно ви хочете чи потребуєте цього контролю, адже навіть на банальному прикладі, наведеному вище, ви бачите, що, хоча є значне поліпшення продуктивності, воно потребує більш глибоких інвестицій для доступу.


16
@Quonux дякую за коментар. Звичайно, це не "реальна програма". Суть тестів полягала в рефакторному еталоні C #, запропонованому в інших місцях на цій сторінці, як доказ того, що код JITted якось швидше, ніж рідний - це не так, а тест потенційно вводить в оману для нових людей.
U007D

9
@Quonux, чому ти повинен писати так? Такі люди, як ти, змушують мене не любити стартовий потік.
Маркус Кнаппен Йоханссон

5
@MarkusKnappenJohansson У мене був поганий день;), я теж просто людина, зняв свій голос, але моя думка все ще діє. О, будь ласка, не любите ТАК тільки тому, що є кілька "дурних" людей :). Приємного.
Quonux

9
ПОВНІШНЯ НЕЗАБАВНА БЕНЧМАРКА. У версії C ++ ви просто зберігаєте частину пам’яті (а потім дивуєтесь тому, як ця операція займає мікросекунди). У версії C # ви створюєте 5000 ARRAYS (інстанціювання об'єктів у пам'яті). C ++ швидше, ніж C # ... але різниця ніде не перевищує 40% ... зараз він більше в межах <10%. Що ілюструє ваш приклад, це те, що програмісти повинні дотримуватися мови, яку вони обрали (а з вашого профілю очевидно, що ви є кар'єрним програмістом на C ++). У C # ви можете зробити двовимірний масив int[,]... слідуючи прикладу.
nikib3ro

3
З того, що я можу сказати, код у вашому прикладі C ++ буквально просто виділяє пам'ять достроково. Реалізація PROPER C # просто напише "Список <double> arrs = new List <double> (ROWS * COLS)", який виділяє пам'ять, необхідну для індексації двовимірного масиву в 1 розмірному форматі (наприклад, те, що ви робили в C ++). Немає абсолютно жодних причин виділяти двовимірний масив і вручну вирівнювати його - величезна кількість ітерацій у вашому попередньому тесті є причиною неприємної продуктивності. Я думаю, накладні витрати все одно будуть більше в C #, але не на значну суму.
JDSweetBeat

62

З мого досвіду (і я багато працював з обома мовами), головна проблема C # порівняно з C ++ - це високе споживання пам’яті, і я не знайшов хорошого способу контролювати це. Саме споживання пам’яті згодом сповільнить програмне забезпечення .NET.

Ще один фактор полягає в тому, що компілятор JIT не може дозволити собі занадто багато часу для проведення розширених оптимізацій, оскільки він працює під час виконання, і кінцевий користувач помітить це, якщо це забирає занадто багато часу. З іншого боку, компілятор C ++ має весь час, який йому потрібно робити для оптимізації під час компіляції. Цей фактор набагато менш значний, ніж споживання пам'яті, ІМХО.


6
В одному з проектів на роботі нам довелося видобувати велику кількість даних одночасно, включаючи зберігання багатьох ГБ пам’яті одночасно та проведення дорогих обчислень на всьому цьому - це вимагало точного контролю над усіма розподілами, C ++ був майже єдиним вибором. +1 для C ++. З іншого боку, це був лише один проект, ми витрачали більшість свого часу на написання систем, які взаємоділи з повільними тренажерами, і налагодження могло бути кошмаром, тому я хотів би, щоб ми могли використовувати мову, оптимізуючу програміст-час для всіх інших речі.
Богатир

7
@IngeHenriksen: Я добре знаю схему розпорядження, але це зовсім не допомагає керованій пам'яті.
Неманья Трифунович

10
@IngeHenriksen розпоряджаючись цим лише гарантує, що метод Dispose був викликаний. Утилізація ніколи не звільняє зібрану зі сміттям пам’ять. Метод Dispose призначений лише для очищення некерованих ресурсів, таких як ручки файлів, і не має нічого спільного з управлінням пам'яттю.
doug65536

1
@NemanjaTrifunovic: "Компілятор JIT не може дозволити собі занадто багато часу для проведення додаткових оптимізацій". Чи можете ви навести деякі оптимізації, які не проводяться JIT, тому що це займе занадто багато часу?
Джон Харроп

5
@ user3800527: Навіть якщо додавання оперативної пам’яті завжди було здійснено (а це не так - уявіть, що Microsoft додає оперативну пам’ять кожному користувачеві MS Office), це не вирішить проблему. Пам'ять є ієрархічною, і програма C # матиме набагато більше пропусків кешу, ніж C ++.
Неманья Трифунович

35

Один конкретний сценарій, коли C ++ все ще має перевагу (і буде на довгі роки), коли поліморфні рішення можуть бути заздалегідь визначені під час компіляції.

Взагалі, інкапсуляція та відкладене прийняття рішень - це гарна річ, оскільки робить код більш динамічним, легше адаптуватися до змін, що змінюються, та легше використовувати як рамки. Ось чому об’єктно-орієнтоване програмування в C # є дуже продуктивним і його можна узагальнити під терміном «узагальнення». На жаль, саме цей вид узагальнення приходить до витрат за час виконання.

Зазвичай ця вартість є несуттєвою, але є додатки, де накладні витрати виртуальних методів та створення об'єктів можуть змінити ситуацію (тим більше, що віртуальні методи запобігають іншим оптимізаціям, таким як вбудований виклик методу). Тут C ++ має величезну перевагу, оскільки ви можете використовувати шаблони для досягнення іншого типу узагальнення, яке не впливає на час виконання, але не обов'язково є менш поліморфним, ніж OOP. Насправді всі механізми, що складають OOP, можна моделювати, використовуючи лише шаблонні методи та роздільну здатність компіляції.

У таких випадках (і правда, вони часто обмежуються спеціальними проблемними доменами), C ++ виграє проти C # та подібних мов.


6
Насправді, віртуальні віртуальні машини Java (і, мабуть, .NET) намагаються уникнути динамічної розсилки. В основному, якщо є спосіб уникнути поліморфітів, ви можете бути впевнені, що ваш ВМ це зробить.
Мартін Пробст

3
+1 У мене завжди виникають труднощі пояснити це моїм колегам з C #, які знають мало C ++ таким чином, щоб вони могли оцінити значення. Ви досить добре це пояснили.
Роман Старков

9
@crtracy: ви робите ставку без високоефективних обчислювальних програм. Розгляньте прогноз погоди, біоінформатику та чисельне моделювання. Показник ефективності C ++ у цих областях не зменшиться, оскільки жоден інший код не може досягти порівнянних показників на тому ж рівні високої абстракції.
Конрад Рудольф

5
@Jon Яблука та апельсини. Ваша конкретна претензія була "C # - це порядки на величину швидше, ніж C ++ в контексті метапрограмування", а не "використання попередньо складеного коду є порядками на швидкість, ніж інтерпретований код". Хоча ми це робимо, ваше твердження про те, що генерація коду виконання є "загальнішим", ніж генерація коду під час компіляції, також явно невірно - вони мають і сильні, і слабкі сторони. Генерація коду під час компіляції використовує систему типів для забезпечення безпеки статичного типу - генерація коду виконання не може цього зробити ( може забезпечити високу безпеку типу, але не статичну безпеку).
Конрад Рудольф

5
@ user3800527 Я думаю, що ви пропустили всю точку цієї відповіді. Звичайно, ви можете обійти це, порушивши інкапсуляцію і опустившись до структур низького рівня - ви можете написати збірку на (більшій частині) будь-якій мові. Те, що робить C ++ (майже) унікальним і унікальним чином підходить для високопродуктивного програмування, - це те, що ви можете створювати абстракції високого рівня, які не вимагають витрат на виконання. Таким чином, вам не потрібно писати схожий на збірний код у C ++, щоб отримати преміальну продуктивність: добре написаний sort(arr, generic_comparer)буде таким же ефективним, як і рукописний цикл на C ++. Це ніколи не буде в C #.
Конрад Рудольф

20

C ++ (або C з цього приводу) дає точний контроль над вашими структурами даних. Якщо ви хочете трохи-скрутити, у вас є такий варіант. Великі керовані програми Java або .NET (OWB, Visual Studio 2005 ), які використовують внутрішні структури даних бібліотек Java / .NET, несуть багаж із собою. Я бачив сесії дизайнерів OWB, використовуючи понад 400 МБ оперативної пам’яті та BIDS для кубового або ETL- дизайну, потрапляючи і в 100 МБ.

На передбачуваному навантаженні (наприклад, у більшості еталонів, які повторюють процес багато разів) JIT може отримати код, який оптимізований досить добре, що практичної різниці немає.

ІМО у великих додатках різниця полягає не стільки в JIT, скільки в структурах даних, які використовує сам код. Якщо програма важка для пам'яті, ви отримаєте менш ефективне використання кешу. Пропуски кешу на сучасних процесорах досить дорогі. Там, де C або C ++ справді виграють, там ви можете оптимізувати використання структур даних для гарної гри з кешем процесора.


19

Для графіки звичайний клас C # Graphics значно повільніше, ніж до GDI, доступ до якого здійснюється через C / C ++. Я знаю, що це не має нічого спільного з мовою, як і раніше, з загальною платформою .NET, але графіка - це те, що пропонується розробнику як заміна GDI, а її продуктивність настільки погана, що я б навіть не наважувався робити графіку з цим.

У нас є простий орієнтир, який ми використовуємо, щоб побачити, наскільки швидко працює графічна бібліотека, і це просто малювати випадкові лінії у вікні. C ++ / GDI все ще спритний 10000 рядків, тоді як C # / Graphics має труднощі робити 1000 в режимі реального часу.


5
Мене заінтригувала ваша відповідь. Чи ви протестували те саме тестове поле з небезпечним кодом і блокувальними блоками, і самостійно малювали випадкові лінії? Тепер це було б цікаво подивитися.
Педері

2
@Pedery nope у мене немає. просто використання GDI та .NET.Graphics найпростішими способами. що ви маєте на увазі під «малюванням самих випадкових ліній»?
QBziZ

1
Тоді вам, можливо, варто подумати про тестування цього, щоб отримати більш реалістичні показники того, наскільки швидким може бути C #. Ось приємний огляд методики: bobpowell.net/lockingbits.htm
Педері

6
Це не те, що ми хочемо робити, самі помістивши окремі пікселі в буфер кадру. Якщо вам доведеться все реалізовувати самостійно, який сенс мати API / платформу для кодування? Для мене це неаргумент. Нам ніколи не потрібно було розміщувати окремі пікселі в framebuffer в GDI для малювання ліній, і ми не плануємо цього робити в .NET. На мою думку, ми використовували реалістичну метрику, і .NET виявився повільним.
QBziZ

1
Ну, я маю лише невелике уявлення про те, що таке виявлення кропив'янки, але лише зазначення одного терміну швидше нічого не підтверджує. Ви написали його на C ++? У JavaScript? І порівняли ті, що в C #? І крім цього, я не думаю, що для виявлення блобу використовується багато графічних примітивів. Виправте мене, якщо не так, але я думаю, що це статистичні алгоритми, що виконують операції над пікселями.
QBziZ

13

Збір сміття є основною причиною використання Java # CANNOT для систем реального часу.

  1. Коли відбудеться GC?

  2. Як багато часу це займе?

Це недетерміновано.


5
Я не є великим шанувальником Java, але ніщо не говорить про те, що Java не може використовувати GC в режимі реального часу.
Zan Lynx

5
Є багато реалізацій GC в реальному часі, якщо ви хочете подивитися. (GC - область, яка переповнена науково-дослідними роботами)
Арафангіон

FWIW Річард Джонс щойно опублікував оновлену версію своєї книги з вивезення сміття, яка, серед іншого, висвітлює новітні дизайни GC в реальному часі.
Джон Харроп

11
Це дурницький аргумент, Windows (і Linux) - це не в реальному часі. Ваш C ++-код може бути замінений на кількість 18 мс-слотів також у будь-який час.
Хенк Холтерман

2
@HenkHolterman Щоправда, але ви завжди можете написати завантажувач у зборі, прив’яжіть його до завантажувального ядра для вашої програми та виконайте свої програми C ++ безпосередньо проти обладнання (в RT btw). Ви не можете цього зробити в C #, і будь-які зусилля, які я бачив, лише імітують попередньо складену збірку в C # і використовують тону коду С, що робить безглуздішим використання C #. Читати все це якось смішно, оскільки C # по-справжньому марний без .NET рамки.
zackery.fix

11

Нам довелося визначити, чи C # порівняно з C ++ у продуктивності, і я написав для цього кілька тестових програм (використовуючи Visual Studio 2005 для обох мов). Виявилося, що без збирання сміття та лише з урахуванням мови (а не рамки) C # має в основному таку ж ефективність, що і C ++. Розподіл пам’яті набагато швидше в C #, ніж у C ++, і C # має незначну перевагу в детермінізмі, коли розміри даних збільшуються за межами лінії кешу. Однак усе це довелося заплатити за останній час, і існує велика вартість у вигляді недетермінованих звернень до ефективності для C # через вивезення сміття.


1
У C ++ у вас є можливість використовувати різні методи розподілу, тому залежно від того, як була розподілена пам'ять (AOT?) У C #, це можна зробити так само (але набагато швидше) у C ++.
zackery.fix

5
@ zackery.fix .NET має цікаву перевагу в розподілі купи, оскільки йому потрібно лише перемістити вказівник для виділення нового об'єкта. Це можливо лише завдяки ущільнювачу сміттєзбірника. Звичайно, ви можете зробити те ж саме в C ++, але C ++ не робить цього. Смішно, як ви використовуєте той самий аргумент, щоб сказати "C # міг, але ні, значить, це сміття" і "C ++ не, але це могло, так це приголомшливо" :)
Luaan

9

Як завжди, це залежить від програми. Є випадки, коли C #, ймовірно, незначно повільніше, та інші випадки, коли C ++ в 5 або 10 разів швидше, особливо у випадках, коли операції легко SIMD'd.


Найкращим випадком для VM буде компіляція згенерованого коду під час виконання (наприклад, для відповідності звичайному вираженню, прочитаному під час виконання), оскільки статично складені програми C ++ ванілі можуть використовувати лише інтерпретацію, оскільки в них немає вбудованого компілятора JIT.
Джон Харроп

Зверніть увагу на майбутнє: .NET має підтримку SIMD та друзів приблизно з 2014 року, хоча він не використовується широко.
Луань

9

Я знаю , що це не те , що ви просили, але C # часто швидше писати , ніж C ++, яка є великим бонусом в комерційних умовах.


2
Я б сказав, що це швидше більшу частину часу :)
Пастка

8

C / C ++ може набагато краще працювати в програмах, де є або великі масиви, або великі петлі / ітерації над масивами (будь-якого розміру). Це причина, що графіка, як правило, набагато швидша в C / C ++, оскільки важкі операції з масивом лежать в основі майже всіх графічних операцій. .NET відомий повільно в операціях індексації масиву через усі перевірки безпеки, і це особливо стосується багатовимірних масивів (і, так, прямокутні масиви C # навіть повільніше, ніж нерівні масиви C #).

Бонуси C / C ++ найбільш яскраво виражені, якщо дотримуватися безпосередньо покажчиків та уникати Boost std::vectorта інших контейнерів високого рівня, а також inlineбудь-яку можливу функцію. Використовуйте масиви старої школи, коли це можливо. Так, вам потрібно буде більше рядків коду, щоб виконати те саме, що ви робили в Java або C #, оскільки ви уникаєте контейнерів високого рівня. Якщо вам потрібен масив з динамічним розміром, вам просто потрібно запам'ятати, щоб поєднати вашnew T[] із відповідним delete[]оператором (або використовувати)std::unique_ptr) - ціна на додаткову швидкість полягає в тому, що ви повинні ретельніше кодувати. Але в обмін ви зможете позбутися від накладних витрат керованої пам’яті / збору сміття, яка може легко складати 20% або більше часу виконання сильно об’єктно-орієнтованих програм як у Java, так і .NET, а також тих масових керованих Індексація витрат масиву пам'яті. Програми C ++ також можуть скористатися вигідними комутаторами компілятора в певних конкретних випадках.

Я експерт-програміст із C, C ++, Java та C #. Нещодавно у мене була рідкісна нагода реалізувати ту саму алгоритмічну програму на останніх 3-х мовах. У програмі було багато математичних та багатовимірних операцій з масивом. Я сильно оптимізував це на всіх 3 мовах. Результати були типовими для того, що я зазвичай бачу в менш суворих порівняннях: Java була приблизно на 1,3 рази швидшою, ніж C # (більшість JVM оптимізованіші, ніж CLR), а версія C ++ вказівника в 2,1 рази швидша, ніж C #. Зауважте, що програма C # використовувала лише безпечний код - на мою думку, ви можете також кодувати її в C ++, перш ніж використовувати unsafeключове слово.

Щоб хтось не думав, що я щось проти C #, я закрию, кажу, що C # - це, мабуть, моя улюблена мова. Це найбільш логічна, інтуїтивна та швидка мова розвитку, з якою я стикався до цих пір. Я роблю всі свої прототипи на C #. Мова C # має багато невеликих, тонких переваг перед Java (так, я знаю, що Microsoft мав шанс виправити багато недоліків Java, ввійшовши в гру пізно і, можливо, копіюючи Java). Тост Calendarкогось класу Java ? Якщо Microsoft коли-небудь витратить реальні зусилля для оптимізації CLR та .NET JITter, C # може серйозно взяти на себе. Я чесно здивований, що вони цього ще не зробили - вони зробили стільки справ прямо на мові C #, чому б не зробити це за допомогою важких оптимізацій компілятора? Можливо, якщо ми всі благаємо.


3
"вам просто потрібно запам'ятати, щоб з'єднати своє new T[]з відповідним delete[]" - Ні, ви цього не зробите. Це std::unique_ptrпотрібно зробити для вас.
emlai

якщо припустити, що ви щось написали в графіці, чому пишете безпечний код в c #, ви думали про використання небезпечного коду та порівняння ще раз?
користувач3800527

7

> З того, що я чув ...

Здається, ваша складність полягає у вирішенні питання про те, що почуте ви є надійним, і ця складність буде просто повторена, коли ви спробуєте оцінити відповіді на цьому веб-сайті.

Як ти вирішиш, чи те, що люди тут говорять, більш-менш достовірні, ніж те, що ви спочатку чули?

Одним із способів було б вимагати доказів .

Коли хтось стверджує, що "є деякі області, в яких C # виявляється швидшим за C ++", запитайте їх, чому вони це говорять , попросіть їх показати вам вимірювання, попросіть їх показати вам програми. Іноді вони просто помиляться. Іноді ви дізнаєтесь, що вони просто висловлюють думку, а не діляться чимось, що вони можуть виявити правдою.

Часто інформація та думка змішуються в тому, що люди стверджують, і вам доведеться спробувати розібратися, що це таке. Наприклад, з відповідей на цьому форумі:

  • "Візьміть орієнтири на веб-сайті http://shootout.alioth.debian.org/ з великою скептичністю, оскільки вони значною мірою перевіряють арифметичний код, який, швидше за все, зовсім не схожий на ваш код."

    Запитайте себе, чи дійсно ви розумієте, що означає "ці багатозначні арифметичні коди" , а тоді запитайте себе, чи автор насправді показав вам, що його твердження є правдивим.

  • "Це досить марний тест, оскільки це дійсно залежить від того, наскільки оптимізовані окремі програми; мені вдалося прискорити деякі з них в 4-6 разів і більше, даючи зрозуміти, що порівняння між неоптимізованими програмами досить нерозумно ».

    Запитайте себе, чи автор насправді показав вам, що йому вдалося «пришвидшити деякі з них в 4-6 разів і більше» - це легко заявити!


Я не міг більше з вами погодитися, і саме тому я попросив на цьому форумі ... Зрештою, відповіді повинні бути десь, чи не так? :)
Пастка

1
Так. Відповідь - "Це залежить".
user49117

6

Що стосується проблем із "химерною паралельністю", під час використання Intel TBB та OpenMP на C ++ я спостерігав приблизно 10-кратне підвищення продуктивності порівняно з аналогічними (чисто математикою) проблемами, виконаними з C # і TPL. SIMD - це одна з областей, де C # не може конкурувати, але у мене також склалося враження, що TPL має значні накладні витрати.

З огляду на це, я використовую лише C ++ для вирішальних для виконання завдань, де я знаю, що зможу багатопотоково і швидко отримати результати. Для всього іншого, C # (а іноді і F #) просто чудово.


5

Це надзвичайно розпливчасте запитання без реальних остаточних відповідей.

Наприклад; Я вважаю за краще грати в 3D-ігри, створені в C ++, ніж у C #, тому що продуктивність, безумовно, набагато краща. (І я знаю XNA тощо), але він не підходить до реальної речі.

З іншого боку, як було сказано раніше; ви повинні розвиватися мовою, яка дозволяє швидко робити те, що ви хочете, а потім, якщо необхідно, оптимізувати.


4
Чи можете ви назвати кілька прикладів? Ігри, написані на C # те, що ти знайшов повільним
Карл

1
Навіть приклади програм, які постачалися з установкою, відчували себе повільно.
Давид Чоловік

9
Збирач сміття є величезною відповідальністю в проведенні ігор із C #, оскільки він може вистрілити в будь-який час, викликаючи великі паузи. Явне управління пам’яттю стає простішим для розробки ігор.
постфутурист

3
Більшість сучасних ігор обмежені графічним процесором. Для таких ігор не має значення, чи логіка (виконується на процесорі) на 10% повільніше, вони все ще обмежені GPU, а не процесором. Збір сміття є справжньою проблемою, яка спричиняє випадкові короткі заморозки, якщо розподілення пам'яті не налаштовано належним чином.
Майкл Ентін

2
@postfuturist: Це не вірно на ПК; сміттєзбірник виконує таку гарну роботу, щоб потрапити і виїхати, я ніколи не відчував з цим жодних проблем. Однак на XBox 360 та Zune / Windows-7-Phone сміттєзбірник не настільки розумний, як на ПК; Я ніколи не писав ні для кого , але люди, які сказали мені, збирач сміття - це величезна проблема.
BlueRaja - Danny Pflughoeft

5

Мови .NET можуть бути такими ж швидкими, як код C ++ або навіть швидше, але код C ++ матиме більш постійну пропускну здатність, оскільки час виконання .NET повинен робити паузу для GC , навіть якщо він дуже розумний щодо пауз.

Отже, якщо у вас є якийсь код, який повинен постійно працювати швидко, без пауз, .NET вводить затримку в якийсь момент , навіть якщо ви дуже обережні з робочим часом GC.


6
-1: Це насправді міф. По-перше, затримка ідіоматичного C ++ насправді жахлива і часто набагато гірша, ніж .NET, оскільки RAII спричиняє лавини деструкторів, коли великі структури даних випадають із сфери застосування, тоді як сучасні GC є поступовими, а .NET навіть одночасно. По-друге, ви можете фактично повністю видалити паузи GC у .NET, не виділяючи.
Джон Харроп

2
Якщо ви це зробите, то вам доведеться відмовитися від використання BCL, оскільки більшість методів створюють перехідні об'єкти.
Флоріан Дойон

5
Це цілком вірно, лише до .net 4 ГК зробили поступовим. У нас є великий додаток C #, який робить паузи на секунди одночасно для GC. Для критично важливих програм це вбивця.
Джастін

5
Існує причина, через яку програми, які прагнуть апаратно використовувати, як правило, використовують C ++. У вас є більш тонкий налаштований контроль, коли вам це потрібно. Продуктивність є ключовою лише під час натискання системи, інакше використовуйте C # або Java, щоб заощадити ваш час.
VoronoiPotato

4
якщо ви не можете керувати кеш-поведінкою, ви не можете перемогти оптимізований код c ++. Пропуск кешу з L1 в основну пам'ять може уповільнити вашу роботу в 100 разів.
DAG

4

Теоретично, для тривалого запуску додатків типу сервера мова, складена на JIT, може стати набагато швидшою, ніж у власне складеного аналога. Оскільки мова, зібрана в JIT, як правило, спочатку збирається на проміжну мову досить низького рівня, то в будь-який час ви можете зробити багато оптимізацій високого рівня прямо під час компіляції. Велика перевага полягає в тому, що JIT може продовжувати перекомпілювати розділи коду на ходу, оскільки отримує все більше даних про те, як використовується програма. Він може організувати найпоширеніші кодові шляхи, щоб дозволити передбаченню гілок досягти успіху якомога частіше. Він може перевпорядкувати окремі блоки коду, які часто викликаються разом, щоб зберегти їх обидва в кеші. Це може витратити більше зусиль на оптимізацію внутрішніх петель.

Я сумніваюся, що це робиться .NET або будь-яким з JRE, але це було досліджено ще тоді, коли я був в університеті, тому нерозумно думати, що подібні речі незабаром можуть знайти свій шлях у реальний світ .


4

Програми, які потребують інтенсивного доступу до пам'яті, наприклад. Маніпулювання зображеннями, як правило, краще записати в некерованому середовищі (C ++), ніж керувати (C #). Оптимізовані внутрішні петлі з арифметикою вказівника набагато простіше мати управління в C ++. У C # вам може знадобитися вдатися до небезпечного коду, щоб навіть наблизитися до однакової продуктивності.


4

Я тестував vectorC ++ і C # еквівалент - Listі прості 2d масиви.

Я використовую випуски Visual C # / C ++ 2010 Express. Обидва проекти - це прості консольні програми, я протестував їх у стандартному (без спеціальних налаштувань) режимі випуску та налагодження. Списки C # працюють швидше на моєму ПК, ініціалізація масиву також швидша в C #, математичні операції повільніші.

Я використовую Intel Core2Duo P8600@2.4GHz, C # - .NET 4.0.

Я знаю, що реалізація вектора відрізняється від списку C #, але я просто хотів протестувати колекції, які я б використовував для зберігання своїх об'єктів (і був у змозі використовувати індексний аксесуар).

Звичайно, вам потрібно очистити пам'ять (скажімо, для кожного використання new), але я хотів, щоб код був простим.

С ++ векторний тест :

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);
}

Тест списку 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);
}

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;
}

C # - масив:

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);

}

Час: (реліз / налагодження)

C ++

  • Масив 600/606 мс init,
  • Заповнення масиву 200/270 мс,
  • 1 сек / 13 сек вектор init & fill.

(Так, 13 секунд, у мене завжди проблеми зі списками / векторами в режимі налагодження.)

C #:

  • Масив 20/20 мс init,
  • 403/440 мс заповнення масиву,
  • Список 710/742 мс init & fill.

1
Я хотів би бачити індекс-аксесуар у std :: list. У будь-якому випадку для списку, режиму випуску потрібно 37 секунд. Випуск без налагодження: список 3s, вектор 0,3 s. Ймовірно, питання відміни або що-небудь. Зразок: nopaste.pl/12fb
Wiory

2
Для точніших вимірювань вам не слід користуватися System.DateTime.Now, а скоріше клас секундомір .
Сем

4
Частина причини, коли ви отримуєте такі повільні часи заповнення для вектора в C ++, це те, що ви використовуєте push_back. Це показано на численних дописах повільніше, ніж використання методу at або оператора []. Для того, щоб використовувати будь-який із цих методів, вам потрібно використовувати метод зміни розміру або резерву. Крім того, причина вашої ініціалізації займає стільки часу для випадку вектора c ++ - це те, що ви змушуєте оператора копіювання чи призначення (не впевнений, що в цьому випадку) ініціалізувати ваш вектор c ++. Для масиву в c ++ існує алгоритм, який використовує 2 нові виклики, а не 5001, а також швидший ітераційний процес.
Захарій Краус

5
Я думаю, ви не робили c ++ належним чином. Лише погляд і знайшов так багато питань. Наприклад, вектор <вектор <подвійний>> мій список = вектор <вектор <подвійний>> ()
DAG

2
Ого. Не впевнений, які висновки можна зробити, порівнюючи списки та змінні масиви, але якщо ви збираєтесь використовувати такі вектори, вам захочеться дізнатися про резерв (), мій друг, резерв ().
U007D

3

Ну, це залежить. Якщо байт-код переведений на машинний код (а не лише JIT) (я маю на увазі, якщо ви виконуєте програму), і якщо ваша програма використовує багато виділень / угод, це може бути швидше, тому що алгоритму GC просто потрібно один прохід (теоретично) через всю пам'ять один раз, але звичайні дзвінки malloc / realloc / вільні C / C ++ викликають накладні витрати на кожен виклик (виклик-накладні витрати, накладні структури даних, кеш пропускає;)).

Так це теоретично можливо (також і для інших мов GC).

Я насправді не бачу крайнього недоліку в тому, щоб не мати можливості використовувати метапрограмування на C # для більшості програм, тому що більшість програмістів так і не використовують його.

Ще одна велика перевага полягає в тому, що SQL, як і "розширення" LINQ , надає можливість компілятору оптимізувати виклики до баз даних (іншими словами, компілятор міг би зібрати весь LINQ до однієї "blob" бінарної, де покликані функції вбудовані або для вашого використання оптимізовано, але я тут спекулюю).


1
Будь-який належний розробник C ++ не зіткнеться з описаними вами проблемами. Ті проблеми, які мають поганий C, які вирішили ляпати класи на своїх програмах і називати це C ++, мають ці проблеми.
Ясніше

1
для любові до богів це 8 років, OMFGz
Quonux


2

Я припускаю, що програми, написані на C #, працюють швидко, а також є більше C ++ написаних додатків, які працюють швидко (ну і C ++ тільки старші ... і брати UNIX теж ...)
- питання справді - що це, річ, користувачі і розробники скаржаться на ...
Ну, IMHO, у випадку C # ми маємо дуже комфортний інтерфейс, дуже приємну ієрархію бібліотек та цілу систему інтерфейсів CLI. У випадку C ++ у нас є шаблони, ATL, COM, MFC і цілий шебанг уже написаного та запущеного коду, як OpenGL, DirectX і так далі ... Розробники скаржаться на невизначено підвищені виклики GC у випадку C # (означає, що програма працює швидко, і за одну секунду - чуб! вона застрягла).
Писати код у C # дуже просто та швидко (не забувати, що також збільшується ймовірність помилок. У разі C ++ розробники скаржаться на витоки пам'яті, - означає розчарування, дзвінки між DLL, а також "пекло DLL" - проблема з підтримка та заміна бібліотек на новіші ...
Я думаю, що чим більше ви будете володіти мовою програмування, тим більше якість (та швидкість) буде характеризувати ваше програмне забезпечення.


2

Я сказав би це так: програмісти, які пишуть швидший код, ті, хто більш обізнаний про те, що змушує швидкодіяти поточні машини, і, до речі, вони також є тими, хто використовує відповідний інструмент, що дозволяє чітко визначати низький рівень та детермінованість методики оптимізації. З цих причин саме ці люди використовують ті, хто використовує C / C ++, а не C #. Я б пішов так далеко, констатуючи це як факт.


Виріжте закодований Minecraft досить швидко, враховуючи кількість даних, якими він маніпулює. Крім того, він зашифрував це здебільшого одноосібно за порівняно короткий проміжок часу, що було б практично неможливо на C ++. Я погоджуюся з методами оптимізації - якщо у вас є додатковий 10-разовий час розробки, щоб ваш код працював удвічі швидше, він, мабуть, того вартий.
Білл К

2

Якщо я не помиляюся, шаблони C # визначаються під час виконання. Це має бути повільніше, ніж тимчасові шаблони компіляції C ++.

І коли ви використовуєте всі інші оптимізації часу компіляції, про які згадує так багато інших, а також відсутність безпеки, яка справді означає більшу швидкість ...

Я б сказав, що C ++ - це очевидний вибір з точки зору необмеженої швидкості та мінімального споживання пам'яті. Але це також перетворює на більше часу на розробку коду та гарантування того, що ви не просочуєтесь пам'яттю або не спричиняєте будь-яких виключень з нульових покажчиків.

Вердикт:

  • C #: Швидший розвиток, повільніша робота

  • C ++: повільний розвиток, швидший запуск.


1

Це дійсно залежить від того, що ви намагаєтеся зробити у своєму коді. Я чув, що це просто міська легенда про те, що між VB.NET, C # та керованим C ++ є різниця в продуктивності. Однак я виявив, принаймні у порівнянні рядків, що керований C ++ відбиває штани від C #, що, в свою чергу, відбиває штани від VB.NET.

Я ні в якому разі не робив вичерпних порівнянь алгоритмічної складності між мовами. Я також просто використовую налаштування за замовчуванням для кожної з мов. У VB.NET я використовую налаштування, щоб вимагати декларування змінних тощо. Ось код, який я використовую для керованого C ++: (Як ви бачите, цей код досить простий). Я запускаю те ж саме на інших мовах у Visual Studio 2013 з .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;
}

1

Існують деякі основні відмінності між C # і C ++ в аспекті продуктивності:

  • C # на основі GC / купи. Сам розподіл і GC є накладними, як не локальність доступу до пам'яті
  • C ++ оптимізатори стали дуже хорошими з роками. Компілятори JIT не можуть досягти такого ж рівня, оскільки вони мають обмежений час компіляції і не бачать глобальної сфери

Крім цього, роль відіграє також компетентність програміста. Я бачив поганий код C ++, де класи, які передаються за значенням, як аргумент в усьому місці. Насправді ви можете погіршити продуктивність на C ++, якщо не знаєте, що робите.


0

> Зрештою, відповіді повинні бути десь, чи не так? :)

Гм, ні.

Як зазначалося в кількох відповідях, питання недостатньо визначене способами, які запрошують запитання у відповідь, а не відповіді. Щоб взяти лише один спосіб:

А потім які програми? Яка машина? Яка ОС? Який набір даних?


Я повністю згоден. Цікаво, чому люди очікують точної відповіді (63,5%), коли вони задають загальне запитання. Я не думаю, що немає загальної відповіді на таке питання.
зателефонуйте мені Стів

@callmesteve: Я знаю, що ти маєш на увазі, але твоє останнє речення повинне звучати як цвяхи над крейдовою дошкою для будь-якого програміста.
Wouter van Nifterick

1
Схоже, це не відповідає на запитання, і читається більше як коментар чи дзвінка.
Тас

-13

Надихнувшись цим, я зробив швидкий тест із 60 відсотками загальних інструкцій, необхідних для більшості програм.

Ось код 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();
}

Для включення цих інструкцій цілеспрямовано використовуються рядкові масиви та масив.

Ось код 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();
}

Розмір вхідного файлу, який я використовував, становив 40 Кб.

І ось результат -

  • Код C ++ пробіг за 9 секунд.
  • C # код: 4 секунди !!!

О, але це було в Linux ... З C # працює на Mono ... І C ++ з g ++.

Гаразд, ось що я отримав у Windows - Visual Studio 2003 :

  • C # код пробіг за 9 секунд.
  • C ++ код - жахливі 370 секунд !!!

7
Ви там використовуєте різні структури даних та код бібліотеки, хоча "370 секунд" вказує на щось жахливе - ви не запускаєте це у налагоджувачі випадково? Я підозрюю, що ефективність бібліотеки CSV, яку ви використовуєте, цікавіша, ніж продуктивність мови, якою ви користуєтесь. Я б поставив під сумнів використання вектора в цьому контексті та які оптимізації ви використовували. Крім того, широко відомо, що iostreams (зокрема, "myfile << * j <<", ";") набагато повільніше, ніж інші способи запису у файл, принаймні для деяких загальних реалізацій.
Арафангіон

6
Нарешті, ви робите більше роботи у версії C ++. (Чому ви очищаєте csvColumn, csvElement та csvLines?)
Arafangion

2
Кожна ітерація циклу while буде руйнувати та реконструювати std :: istream та std :: vector та std :: string. Хоча тіло виходить за межі кожної ітерації, всі ті змінні, що знаходяться всередині, в той час як область буде зруйновані і побудовані на кожній ітерації.
doug65536

1
з вигляду читання коду c ++ ви намагаєтесь скопіювати з одного файлу в інший файл. Замість використання складних взаємодій між потоками файлів, рядками, векторами та потоковими потоками ви могли просто скопіювати потік вхідного файлу у вихідний потік файлів. Це заощадило б багато часу та пам’яті.
Захарій Краус

2
робити тести на швидкість, перевіряти речі пам’яті, не потрапляйте на диск IO, за винятком випадків тестування на останніх SSD-дисках і присвячених вашому додатку продуктивності. Оскільки комп'ютери постійно записують на диск, навіть якщо ви не торкаєтесь клавіатури.
користувач3800527
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.