Почему мы до сих пор экономим память?
Запись от CoderHuligan размещена 13.03.2021 в 13:10
Показов 13735
Комментарии 85
|
Заголовок может показаться провокационным, но я бы чистосердечно хотел услышать ответ на этот вопрос, и возможно поставить новые.. На самом деле по крайней мере для меня это важно и это один из краеугольных вопросов.. По делам текущим. Последнее время полностью вьезжал в тему использования библиотеки SDL. Прочитал кучу материалов, а сейчас на данном этапе читаю книжку по работе с sdl на английском, так как на русском такой литературы днем с огнем не отыщешь. Благо с английски проблем нет. Так вот, библа это крутая, но для профи, которые знают, что делают. То есть там надо подключать дополнительные библиотеки для расширения функционала и знать внутреннее устройство самой библы для более осознанной и эффективной работы. Это на самом деле хорошо, так как есть базовый стабильный и что самое важное кроссплатформенный функционал, к которому можно добавлять фичи сторонних производителей. Есть и другие библиотеки навроде sfml где все в одной коробке, но она больше заточена на с++, а sdl на чистых сях, что мне по нутру. То есть библа позволяет писать на чистом си и в тоже время иметь графику. Проблема с sdl, хотя и надуманная в том, что например сторонние библы для рисования примитивов надо компилировать самостоятельно, в то время как основная библиотека идет в уже прекомпилированном виде, а это для новичков большой головняк. Есть более старый вариант библы sdl 1.2, а есть sdl 2.0, которая более современная, и имеет повышенный функционал, хотя и в последней нужно вручную компилировать draw функции. В этом большой минус библы, но не существенный. Я прекрасно научился, как подключать в свой проект саму - sdl 1.2 и более новую sdl 2.0, так и подключать и компилировать из сырцов дополнительные расширения в частности draw 1.2.13 и SDL2_gfx-1.0.1 или выше, что вызывает у новичков определенные трудности. Проведено много экспериментов по компиляции dll-ек в mingw code blocks. Так что проблем сейчас у меня с этим нет. более того, если у кого есть проблемы с подключением могу посоветовать или сделать серию уроков в этом блоге. Ход работы с sdl возможно буду освещать тут. На самом деле ничего сложного тут нет. Теперь по теме озвученной в заголовке. Мы до сих пор экономим память? Почему программы стали такими медленными? Об этом из мира IT говорят уже многие. Надо, что называется, зрить в корень проблемы. А корень проблемы лежит в прошлом индустрии. В те далекие времена на заре компьютерной индустрии компьютеры представляли из себя огромные шкафы где мигали электронные лампы, а память была на ферритовых колечках, и её было мало, крайне мало. Приходилось её экономить, считать биты. Именно в этой среде возникали первые парадигмы - процедурная, структурная и пр. Короче говоря, они вознкали в условиях недостатка ОЗУ и ПЗУ. Поэтому самым лучшим решением явилась кратковременная стековая память. Те, кто помнят программируемые микрокалькуляторы типа Б3-34 и др. знают о чем я . В последнем если мне не изменяет память было что-то около 99 ячеек памяти оперативного запоминающего устройства и 4 (?) ячейки регистров стека. В этих спартанских условиях отдельные уникумы ухищрялись писать даже целые игры! Потом возник язык Форт, как некая вершина в развитии стековой архитектуры. Форт можно было запихнуть целиком в ПЗУ и вот тебе целая ОС в кармане. И оно работало. А почему оно работало? Стек примечателен тем, что это не долговременная память, а временная. Тут отдельные ячейки могут использоваться многими компонентами программы, только надо соблюдать определенные соглашения, чтобы не затирать полезную информацию. Таким соглашением, например, является соглашение о передаче параметров между функциями через стек. Это удобно. Каждая функция может что-то оставить на стеке, а может что-то взять оттуда, после чего стек опустошается, как буд-то ничего там и не было. Своеобразный принцип сокрытия информации. Как его тогда понимали, но по моему - ложно понимали.. Более того, если в функции были объявлены внутренние переменные, то при входе в функцию, они тоже располагались в стеке. В том же самом стеке располагался и адрес возврата из функции (в форте для этого был отдельный стек). В чем тут собака порылась? А в том, что вся эта система, которая изначально была призвана экономить память, которой тогда было мало, до сих пор осталась в неизменном виде. То есть сейчас в современных условиях память девать некуда, а мы по прежнему под капотом имеем стек, этот древний стек, куда запихиваем и выпихиваем что-то при каждом входе в функцию или процедуру. В плюс Форту можно приписать то, что его слова-процедуры могли оставлять на стеке много значений, в отличие от например языка Си, функции которого могут оставлять только ОДНО значение. Но это лирика... Собака порылась давно, а яма зияет до сих пор и более того: становится все больше и больше превращаясь постепенно в бездну, которая поглощает всю индустрию.. Посмотрите на среднюю программу - как там мало переменных, и как там много функций и методов. Все потому, что программисты боятся иметь дело с состоянием. Отсюда возникла даже функциональная парадигма, парадигма, которая стремится вообще манипулировать лишь отдельными функциями. Но это перевес в одну сторону, в другую крайность.. Итак, на каждом входе в функцию приходится копировать в стек не только значения параметров, но и внутренние переменные, а это такты, десятки тактов работы процессора. Скажут: современные процы стали гораздо быстрее. А я отвечу: они уже приблизились к максимуму своих возможностей, и дальше уже стена, потолок. Скорость света увы конечна, и движение электрона по проводнику тоже. Дальше путь один - снижать издержки в самом программном обеспечении. ООП еще добавило свои такты и ПО окончательно стало тормозить даже на современных процах. Так почему мы до сих пор остались в стековой парадигме? Ведь время давно уже ушло вперед, зачем экономить на статической памяти? Её нам не хватает? Что за бред! Как раз сейчас её у нас завались, а мы до сих пор программируем на системах по сути неотличимых от программируемого калькулятора из 70-х. годов прошлого века! Это не смешно.. Это реальность.. Почему так произошло?. Ну, вот, изобрели структурную парадигму, которая была призвана избавить мир от "спагетти-кода", от различных переходов, от оператора goto. Но, вскоре выяснилось, что структурная парадигма хороша лишь на бумаге, и в головах теоретиков от информатики, а на практике, без goto иногда обойтись трудно, во всяком случае приходится городить ненужные костыли и напрягать процессор дополнительными тактами, а листинги стало также трудно читать, как и с goto. Что придумали? Процедурную парадигму. Делить код на маленькие участки, и вызывать их, а не переходить на них. Это как бы должно было уменьшить проблему читаемости. И это на самом деле неплохой подход делить код на функции, которые можно было отлаживать по отдельности. Но проблема только усугубилась, так как чем больше функций, тем больше стековых операций, призванных единственно поддерживать определенную парадигму, причем на аппаратном уровне, а не на уровне приложений.. Мало того, что сам по себе стек не резиновый и в реальности глубокие рекурсии, которые позволяла парадигма, были не возможны, но что хуже, программисты привыкли использовать в функциях автоматические переменные, которые на стадии исполнения загружались в стек. Скажут: но есть же статические переменные, пользуйтесь ими. Например в языке Си можно в функции определить переменную как static, и она еще на стадии компиляции будет образована в статической памяти, например в секции data. Причем эту переменную будет видеть лишь эта самая функция и никто другой! А во время исполнения ничего копироваться в стек не будет, что убыстряет программы! Возможность такая есть, и это хорошо. Плохо то, что в си отсутствует возможность скрывать информацию в направлении заданном программистом на уровне языка. Например иметь две функции a и b где функция a будет видеть лишь определенные переменные в функции b, а функция b будет видеть определенные переменные в функции a, а эти переменные бы располагались в статической памяти. Своеобразный обмен сообщениями.. Чтобы этого добиться сейчас нужно использовать глобальные переменные и соглашения об наименовании, но это топорно. Опять на лицо поддержка только определенной жестко заданной кем-то и когда-то парадигмы. Если бы каждая функция имела статические переменные, и определенные видимости для каждой переменной, то мы бы избавились от постоянного копирования автоматических переменных, - памяти то завались, что её экономить, - это раз. Мы бы могли не копировать неизменяемые аргументы повторно при входе в функцию, это два. Например, у нас есть имя файла, что есть константа. Мы несколько раз открываем и закрываем этот файл. Зачем же при каждом вхождении в функцию копировать это значение, которое уже раз использовалось при первом вызове функции? На лицо - чистейший перерасход логики и здравого смысла. И так во всем. Не на функции надо делить программы, а на некие блоки кода, со своими собственными пулами статической памяти, которая может разделяться другими блоками или не разделяться, а также другими пулами, если памяти все таки мало. А следить за всем этим делом должен компилятор, как мы уже догадались. Возврат из блоков может быть как в обычных функциях, неявно, но может быть и в любую другую точку, но в этом случае определять это должен сам программист явно. Это непроцедурный язык но с процедурами. А как же с рекурсией быть? А рекурсию оставим другим языкам. Если кому-то нужна рекурсия, то используйте их. Пусть хотя бы один язык будет без этой возможности, но будет быстрым, эффективным и безопасным (так как весь цимус зла в стеке).. |
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 85
Комментарии
-
Запись от CoderHuligan размещена 13.03.2021 в 16:30
-
Почему мы до сих пор экономим память?
...
этот вопрос аналогичен следующему:
Почему мы до сих пор экономим деньги?
Ответов много и все они будут верными... или нет?Запись от wer1 размещена 13.03.2021 в 18:52
-
Уважаемый CoderHuligan,
Чтобы создать очень быстрый язык программирования, надо избавить его от излишнего контроля. Ведь контроль - это лишний код, который поглощает время работы процессора. Или нет?
1. пусть он делит на 0 (и даёт в ответе 0)
2. пусть любая (ну почти любая) некорректная операция проходит как корректная.
Вы конечно имеете своё мнение по этому вопросу?Запись от wer1 размещена 13.03.2021 в 19:00
-
Стек?
...
Стек вещь интересная. А может ли заменить стек массив с двумя текущими входами?Запись от wer1 размещена 13.03.2021 в 19:02
-
Не только в Си можно определить переменную как STATIC. В бейсике есть тоже такая возможность. Но почему то она практически никем не используется. Что это? Пятое колесо у телеги?... Мне тоже хотелось бы увидеть код мини-программы, которая бы показала пользу этого колеса. Ведь это придумали умные люди. Или они ошиблись?Запись от wer1 размещена 13.03.2021 в 19:11
-
БЗ-34
...
Это базовая модель программируемого микрокалькулятора. Там используется свой язык программирования. Я бы назвал его десятичным ассемлером. Там три вида памяти. Программная память (кажется на 64 шага, но не помню). Стек на 3 числа и 8 регистров для хранения чисел. В прочем задачи были тоже интересные. Как поместить в один регистр два числа?Запись от wer1 размещена 13.03.2021 в 19:20
-
Контроль на стадии компиляции не помешает. Но сейчас все увлеклись контролем на стадии исполнения, что чревато замедлением работы ПО.
Сообщение от wer1
Массив с двумя текущими входами это классическая очередь. Естественно стек она заменить не может, так как используется для других вещей.
Сообщение от wer1
Почему не используется? Из-за студентов-недоучек, или тех, кто книжки читает, но до конца не дочитывает.
Сообщение от wer1
Сплошь и рядом в стек пихают даже целые массивы. Мыщьх писал, что за размещение массивов в стеке давно пора расстреливать, но воз стал еще тяжелее..
смотря регистр какого размера и какие числа нам нужны. Поместить в один регистр два числа - тривиальная операция.
Сообщение от wer1
Запись от CoderHuligan размещена 14.03.2021 в 10:10
-
Запись от CoderHuligan размещена 14.03.2021 в 10:11
-
Предлагаете программировать исходя из того, что пользователь, например, всегда вводит гарантировано допустимые данные, которые (опять же например) гарантировано ни когда не приведут к делению на 0 ? Или как упомянули выше выдавать в "случае чего" неведомую хрень?
Сообщение от CoderHuligan
Т.е. считает бухгалтер вам зарплату, по какой то причине (которая в современных "непутевых" программах приводит к отображению ошибки типа "Вы забыли человеку рабочее время указать") получается 0..... Вы идете в бухгалтерию.... Ну и с осознанием того, что "зато быстро и не тратятся лишние такты" - спокойно пойдете восвояси с пустым кошельком?
Или вы о чем то другом "про все увлеклись контролем"? Или компилировать под все ситуации отдельные программы (чтоб вообще не требовалось ни какого ввода)?Запись от voral размещена 14.03.2021 в 18:35
-
Причем здесь это? Проверять ввод пользователя - священная обязанность программиста, а не виртуальной машины. Речь шла о проверках например во время сборки мусора, о проверках типов. В ООП тоже много проверок на стадии исполнения. Парадигма требует. Также невидимые преобразования типов в интерпретаторах.
Сообщение от voral
Запись от CoderHuligan размещена 14.03.2021 в 18:49
-
При чем тут парадигма? Т.е. вот прям таки если бы делал ФП то этого нечто не потребовалось, а "взял ООП" значит проверяй? Можете минимальный пример привести, чтоб понять о чем вы?
Сообщение от CoderHuligan
В общем тот же вопрос и про преобразования типов в интерпретаторах....Запись от voral размещена 15.03.2021 в 08:06
-
А мне вот не понятно, зачем придумали мого типов переменных?
Ну есть тип LONG для длинных целых чисел
Тогда зачем нужет тип INTEGER?
Или совсем короткий тип BYTE?
А эти типы, в отличие от LONG, работают медленнее. Преобразование типов только тормозит работу программы.
Может кто-нибудь дать логически обоснованный ответ?Запись от wer1 размещена 15.03.2021 в 11:05
-
Опять же для экономии места на компьютерах 50-летней давности. Оттуда ножки рожки растут. Гораздо выгоднее хранить текст в однобайтовой кодировке, чем в 2 или более байтовой. Оперативной памяти жрет меньше и меньше дискового пространства. Однако я против все подвести под один знаменатель. Я за то, чтобы программист сам решал, какой размер чисел ему нужен. а сейчас все идет по пути универсализации и опрощения. Я это не приветствую.
Сообщение от wer1
Запись от CoderHuligan размещена 15.03.2021 в 11:30
-
Ну как же не причем? А что виртуальные методы в ран-тайм не обращаются к таблицам дескрипторов? Именно в ран-тайм! какая еще парадигма этого требует именно в ран-тайм?!! Нужно же решить какой экземпляр класса обратился к конкретному методу и пр. Это одна из проверок.
Сообщение от voral
Про интерпретаторы. А что вы не слышали о типобезопасности? - https://ru.wikipedia.org/wiki/... 1%82%D1%8C
Или никогда на скриптовых ЯП не писали? Не знаете, что при попытке присваивания целой переменной например числа с плавающей точкой происходит преобразование целого типа в вещественный? Ну, что мне элементарные вещи разжовывать? И это происходит в ран-тайм! В скриптах. Какой пример еще привести?Запись от CoderHuligan размещена 15.03.2021 в 11:37
-
Т.е. если я вызываю функцию передавая в нее некоторый параметр его тип не интересует (при решении той же самой задачи)?
Сообщение от CoderHuligan
И какую вы альтернативу предлагаете? Не проверять? Не преобразовывать? Всегда хранить во флоате?
Сообщение от CoderHuligan
Пример где можно понять, что все это "лишняя" и "не нужная" трата ресурсов.
А так да... по теории все лишнее. Проц должен решать за один такт абсолютно любую задачу - все что свыше это не нужная шняга придуманная глупыми инженерами.Запись от voral размещена 15.03.2021 в 12:36
-
предлагаю делать все явно, и уходить от неявного, "по-умолчанию". Преобразовывать тип явно и уходить от скриптовых языков, которые мы так полюбили за последнее время, и от которых так не хочется отвыкать.. Жизнь заставит.. Ран-тайм слишком ненадежная штука, чтобы на него полагаться. Все проверки типов как и все их преобразования должны делаться еще на этапе компиляции, а не трансляции.
Сообщение от voral
А пример - множество программ, которые грузятся десятками секунд, а то и минутами, которые работают абы как и тормозят на каждом клике.Запись от CoderHuligan размещена 15.03.2021 в 13:21
-
А ну т.е. весь ваш поток мыслей в итоге сводится вообще к уходу от интерперетируемых к компилируемым? Не задумывались, что у вас каша просто в голове из-за того что вы сваливаете в одну кучу много разных вопросов?
Угу. Только вот реальная практика говорит совсем о другом. Скриптовые языки во всю развиваются.Да движутся в торону более строгой типизации. Но от проверок типов все равно не избавиться (даже в случае компиляции)
Сообщение от CoderHuligan
Ну и в рантайме достаточно часто есть задачи, когда тип заранее не известен.
Сообщение от CoderHuligan
"множество", "все знают" и прочие подобные выражение это ни о чем.
Сообщение от CoderHuligan
Ну я как-то пересекался с программой с одной. которая по функционалу была ни о чем, а под нее приходилось покупать топовый комп и он при этом тормозил. При этом программа была не то что бы "поделкой школьника для мелкой фирмочки". а программа которой были обязаны пользоваться все оптовые продавцы алкогольной продукции..... Компилируемая..... Тормозила огого..... Delphi виноват? по секрету скажу: нет... разработчик идиот-экспериментатор.
У вас просто нет опыта работы с серьезными проектами. Да, компилированное ПО лучше, быстрее и тп. Но это не главный критерий и не единственный.
Тому же пыху уже сколько лет предрекают гибель?Запись от voral размещена 15.03.2021 в 13:38
-
Что явно нужно приводить в ран-тайме нужно приводить в ран-тайме, никто с этим не спорит.
интерпретаторы создают еще одну прослойку между машиной и программой, что есть виртуальная машина. Да, сейчас научились динамически компилировать, но это увеличивает время загрузки программы, да и нужна опять же виртуальная машина. Программа при этом либо будет таскать эту среду с собой, либо на компе пользователя она должна быть предустановлена, в любом случае это неудобно.
Вы упомянули пых, но ведь это все можно было бы ускорить не в разы, а на порядки, если бы исходный код не надо было постоянно компилировать или интерпретировать. один раз скомпилировав можно запускать эти модули в своем особом пространстве виртуальной машины, чтобы черви не смогли размножаться.. Хотя черви могут прорваться сквозь даже виртуальную машину, но это особые черви..Запись от CoderHuligan размещена 15.03.2021 в 14:45
-
Проблема ваших рассуждений в том, что вы взяли только один фактор и строите выводы только на нем. В теории (и если думать только вот так узко) все так... А на деле....
Сообщение от CoderHuligan
У меня есть собственный проект, я могу писать и на сях и на php. При этом вот так если мыслить "узко" то задача не для PHP (по сути небольшой САПР). И вот поверьте нет особого желания писать его на сях. Посетители на сайте есть, сервер справляется (причем относительно дешевый) по этому, по крайней мере на данном этапе, это (то о чем вы говорите) мало значимый фактор.
Основная цель проекта - приносить мне доход, при этом с возможно минимальными вложениями времени.
Было бы для души, чтоб все делать по феншую - возможно взял бы и Си в большей мере.
При этом, например сравнительно недавно в пыхе появился FFI - инструмент позволяющий более удобно и просто использовать си в проекте... А у меня много работы с кривыми безье. Я попробовал некоторые функции на сях.... Прирост есть значительный... Проблема правда в том, что прирост заметен на выдуманном тесте в котором по сути, тупо дофига итераций. В реальном же расчете пользователь даже не заметит. И по этому, по крайней мере пока, даже при наличии уже готовой либы, в которой есть некоторые функции на бою я это не применяю.Запись от voral размещена 15.03.2021 в 14:59
-
Сервер может справляться если посетителей немного. А если у вас проект типа ютьюба вам не только целый собственный сервер понадобится, но их будет очень много этих серверов. А чтобы сократить издержки на эти "много" надо идти другим путем. То есть вопрос только в масштабе проблемы. Если у сервера посетителей 10 человек в день, то можно на черепашьем языке писать.. а если миллион в час, то такой номер не прокатит.
Большей частью языка си достаточно для любых проектов. Более того, достаточно даже его базовых средств. О чем речь? Речь о том, что даже не нужно создавать какие-то библиотеки, типа работы со списками в динамической памяти, высокоуровневых строк и т.п. потому что это все можно сделать на основе уже существующих массивов: стеки, очереди, списки, деревья. Причем все это будет работать ВРАЗЫ быстрее.. Но это не кошерно, крутые пацаны так не пишут, им подавай Кнута с Виртом. Но это мое мнение. Это не значит, что я не могу список создать или нечто подобное высокоуровневых строк - могу. Списки моей реализации есть в разделе си для начинающих, как и стеки. Более того существует куча сторонних либ для всего этого, поэтому даже заморачиваться не стоит. Я говорю, что можно обойтись базовыми вещами и код будет работать в разы быстрее.
А почему так? потому что рекурсия, списки и пр., это игры непрграммистов, а теоретиков. Реальность достаточно сурова.Запись от CoderHuligan размещена 15.03.2021 в 16:16



