Чи стає управління пам'яттю в програмуванні неактуальним питанням?
Управління пам'яттю (або управлінням) - це фактично головна причина, що я використовую C і C ++.
Пам'ять зараз порівняно дешева.
Не швидка пам'ять. Ми все ще дивимося на невелику кількість регістрів, щось на зразок кеш даних 32 КБ для L1 на i7, 256 Кб для L2 та 2 МБ для L3 / core. Це сказав:
Якщо ми не розмовляємо з точки зору цільових платформ із суворими обмеженнями робочої пам'яті (наприклад, вбудованими системами тощо), чи має використання пам'яті викликати занепокоєння при виборі мови загального призначення сьогодні?
Використання пам'яті на загальному рівні, можливо, ні. Мені трохи непрактично в тому, що мені не подобається ідея блокнота, який займає, скажімо, 50 мегабайт DRAM і сотні мегабайт місця на жорсткому диску, хоча я маю на цьому запас і багато іншого. Я був довгий час, і мені просто здається дивним і люб'язним, коли я бачу, що таке просте додаток має відносно стільки пам’яті для того, що потрібно зробити з кілобайтами. Це означає, що я міг би жити сам із собою, якби зіткнувся з такою річчю, якби все-таки було приємно і чуйно.
Причиною, що для мене важливе управління пам’яттю в моїй галузі, не полягає в тому, щоб в цілому зменшити використання пам'яті. Сотні мегабайт використання пам’яті не обов'язково сповільнюватимуть додаток будь-яким нетривіальним способом, якщо жодна з цієї пам’яті часто не доступна (наприклад, лише після натискання кнопки чи іншої форми введення користувача, що вкрай рідко, якщо ви говорять про корейських гравців Starcraft, які можуть натиснути кнопку мільйон разів на секунду).
Причина, яка є важливою в моєму полі, полягає в тому, щоб щільно пам’ятати і зближувати пам’ять , до якої дуже часто звертаються (наприклад, перекидаються на кожен кадр) на цих критичних шляхах. Ми не хочемо втрачати кеш-пам'ять кожного разу, коли ми отримуємо доступ до лише одного з мільйона елементів, до якого потрібно отримати доступ у циклі кожен кадр. Коли ми переміщаємо пам’ять вниз по ієрархії від повільної пам'яті до швидкої пам’яті великими фрагментами, скажімо, 64-байтними кеш-лініями, це дуже корисно, якщо всі 64 байти містять відповідні дані, якщо ми можемо вмістити кілька елементів, варті даних у ці 64 байти, і якщо наші схеми доступу такі, що ми використовуємо їх до вилучення даних.
Ці часто доступні дані для мільйона елементів можуть охоплювати лише 20 мегабайт, навіть якщо ми маємо гігабайти. Він все ще робить різницю у швидкості кадрів, циркулюючи над цими даними кожен окремий кадр, намальований, якщо пам'ять є тісною і зближеною, щоб мінімізувати пропуски кешу, і саме тут управління / контроль пам'яті настільки корисний. Простий наочний приклад сфери з кількома мільйонами вершин:
Наведене вище насправді повільніше, ніж моя змінна версія, оскільки вона тестує стійке представлення структури мережі в сітці, але, маючи цю сторону, я намагався досягти такої частоти кадрів навіть на половину цих даних (правда, апаратне забезпечення стало швидше з моєї боротьби ), тому що я не отримав змогу мінімізувати пропуски кешу та використання пам'яті для сітчастих даних. Мережі - це одна з найскладніших структур даних, з якою я мав справу з цього приводу, оскільки вони зберігають стільки взаємозалежних даних, які повинні залишатися синхронізованими, як багатокутники, ребра, вершини, стільки карток текстур, скільки користувач хоче прикріпити, кісткові ваги, кольорові карти, набори вибору, морфійові цілі, ваги кромки, матеріали багатокутника тощо тощо тощо.
Протягом останніх кількох десятиліть я розробляв та впроваджував ряд сітчастих систем, і їх швидкість часто була дуже пропорційною їх використанню пам'яті. Незважаючи на те, що я працюю з цим, набагато більше пам’яті, ніж коли я почав, мої нові сітчасті системи в 10 разів швидше, ніж моя перша конструкція (майже 20 років тому), і значною мірою, оскільки вони використовують близько 1/10 пам'ять. Найновіша версія навіть використовує індексовану компресію, щоб скомпонувати якомога більше даних, і, незважаючи на обробку накладних витрат на декомпресію, стиснення насправді покращило продуктивність, оскільки, знову ж таки, у нас так мало дорогої швидкої пам'яті. Зараз я можу вмістити мільйон багатокутних сіток з текстурними координатами, складанням країв, призначенням матеріалів тощо, а також просторовим індексом для цього приблизно в 30 мегабайт.
Ось змінний прототип з понад 8 мільйонами чотирикутників і схемою підрозділу з декількома схемами на i3 з GF 8400 (це було з декількох років тому). Це швидше, ніж моя незмінна версія, але не використовується у виробництві, оскільки я знайшов незмінну версію настільки простішою в обслуговуванні, а показник продуктивності не надто поганий. Зауважте, що каркас не вказує фасети, а патчі (дроти - це фактично криві, інакше вся сітка буде суцільною чорною), хоча всі точки у фасеті змінені пензлем.
Так що все одно, я просто хотів показати дещо з цього вище, щоб показати конкретні приклади та сфери, де управління пам’яттю настільки корисне, а також, сподіваємось, тому люди не думають, що я просто розмовляю з мого прикладу. Я, як правило, трохи дратується, коли люди кажуть, що пам'ять настільки велика і дешева, тому що це говорить про повільну пам'ять, як DRAM і жорсткі диски. Він все ще такий маленький і такий дорогоцінний, коли ми говоримо про швидку пам’ять, а продуктивність для справді критичних (тобто загальних випадків, не для всіх) шляхів стосується відтворення цього невеликого обсягу швидкої пам'яті та використання його настільки ефективно, наскільки ми можемо .
Для подібних речей дуже корисно працювати з мовою, яка дозволяє, наприклад, проектувати об'єкти високого рівня, такі як C ++, при цьому зберігаючи ці об’єкти в одному або декількох суміжних масивах із гарантією, що пам'ять про всі такі об'єкти будуть суцільно представлені і без зайвих накладних пам'яті на один об'єкт (наприклад, не всі об'єкти потребують рефлексії або віртуальної розсилки). Коли ви фактично переходите в ці найважливіші області продуктивності, це насправді стає підвищенням продуктивності, щоб мати такий контроль пам’яті над, скажімо, змішуванням з об'єктами об'єктів та використанням примітивних типів даних, щоб уникнути накладних витрат об’єктів, витрат на GC та зберегти часто доступ до пам’яті. разом суміжні.
Тож управління / контроль пам'яті (або її відсутність) є фактично домінуючою причиною в моєму випадку вибору мови, яка найбільш продуктивно дозволяє мені вирішувати проблеми. Я точно пишу свою частку коду, який не є критичним для продуктивності, і для цього я схильний використовувати Lua, який досить легко вставити з C.