Что до примера: mmap можно? Задаю вопрос именно в таком виде, отвечу развернуто после ответа (можно коротко). Потому что так понятнее будет.
Обсуждать можно что угодно, тем более в рамках concept sanity check.
Но про mmap() не понял.
Замапить файл размером (там size_t параметр) более 2/4 гигабайт - да, этим пожалуй можно найти оправдание 64-х битному size_t. Можно ли иметь файл размером более 2/4 гигабайт - аналогично, конечно можно. Но тут тонкий момент - эти сущности относятся к другому классу памяти - это уже не RAM, а persistent memory.
Изначально меня интересовали размеры контейнеров в RAM, в частности размеров строк (Strings), и зачем их определять как size_t. Именно с позиций практического аспекта, как пример из реальной задачи где есть строки или какой ArrayList количеством символов (элементов) более 2млрд.
А с размерами именно файлов скорее терминологическая путаница, т.к. их размер это фактически верхний предел адресуемого смещения хранилища данных, aka file data offset limit, т.е. off_t и size_t тут по сути одно и тоже, и работают одинаково, и возможно оба просто изначально имеют неудачное название.
void *mmap(size_t length;
void addr[length], size_t length, int prot, int flags, int fd, off_t offset);
Хотя открыв ptrdiff_t, uintptr_t, а также ssize_t - можно пожалуй констатировать, что с удачными названиями и в целом с концепциям в стандартах некоторое фиаско, впрочем, об этом изначально речь и шла, в утверждении что size_t - это инженерный просчет.
Возможно лучшим решением было бы иметь size64_t в дополнение к существующему off64_t
Или просто использование int для строк и тех самых контейнеров по типу ArrayList / vector - последнее наиболее ожидаемое поведение и наиболее оптимальное в части cache friendly - банально больше данных помещается в кэш CPU, меньше промахов и т.д..
The record for the largest volume of RAW data used to create a single image belongs to a 2.05-terapixel panorama of Oslo, Norway (verified by Guinness World Records in 2025). RAW Data: The project used 12.3 TB of RAW files, generated from 366,843 individual photos taken over four days
ООК, фото панорама на 2 терапикселя. Но какой практический смысл даже на этом примере иметь 64 битный size_t?
Даже подобные "картинки" все равно внутри нужно дробить на чанки и отдельно их компрессировать и по отдельным индексированным в каталоге offset хранить (естественно 64 битным). Иначе распаковка solid архива 12 терабайт со скоростью 485MB/s (lossless qoi компрессия) займет около 8 часов (или 3 дня, если в JPEG XL).
В текущих реалиях это не имеет практического смысла. Хотя и утверждается (кем?), что рынок мейнфреймов растет (хотя рынок HP/UX, SPARC, AIX наоборот который год активно замещается на x64/AArch64 Linux решения, парадокс), это слишком специализированная, нишевая архитектура, тем более для OSS и прочих импортозамещений.
Для меня самого ограничения в 48 бит адреса были весьма неожиданным открытием. Казалось бы - можно делать mmap() based databases / raw files размером до практически неограниченных 18 экзабайт, ан нет, верхний лимит в 128 терабайт, а это сильно меньше, чем возможности современных СХД на НЖМД: что-то вроде 47 петабайт в одной стойке, до 1 экзабайта рекорд в CERN.
Хотя возможность произвольно адресовать 1 экзабайт через mmap() выглядела многообещающей, но нет, вам это не нужно ибо не положено :)
Радует, что начали минусовать и хоть что-то писать.
time_t имеет вполне объективную природу - 32 бита никак не хватало для хранения секунд после 2037 года, эту тему вроде закрыли. А там еще и миллисекунды нужны.
Но давайте еще раз с size_t. Можно привести пример контейнера с данными (из реальных задач), которому требуется более 32-бит для индексации элемента? С поправкой на то, что массив из 8-байтных элементов уже займет 32гигабайта памяти.
Этот пост выше был написан именно для этого - покажите хоть одну задачу, где нужен контейнер в ОЗУ на более чем 2млрд. элементов одновременно. Есть примеры?
Байтовые array есть? Есть. Конец.
Чего именно конец? Что в этом байтовом array хранится? Можно пример? Фотография в raw более 4гибайта? И опять-же, off_t это не size_t. Размер это не смещение и не адрес.
Инвесторы в ИИ бум видимо только начинают подозревать, что AI агенты в реальности не сокращают условно 10 программистов, заменяя их на одного писателя SDD промптов. Скорее наоборот - создают еще 20..30 новых рабочих мест, которые будут пытаться взять под контроль и пытаться развивать эти самые нейрослопы. А старые скучные задачи тоже нужно будет кому-то продолжать пилить.
Это же примерно как покупка автомобиля. Экономика владения ненужным для решения выдуманных задач. Сначала безудержная эйфория и радужные представления о том, как много он, личный автомобиль - проблем решит. А уже на втором цикле владения начинаются рекурсивные проблемы владения: постройки гаража, покупки паркоместа, летне-зимней резины, зимней омывайки, антикора, шумки, выбор навигатора, муки с андроидавто, уроки контраварийного вождения, перепрошивки, глюки, удаления катализатора, проблема пробитой резины, первое знакомство с эвакуатором, первое знакомство с инспектором, а там до exist.ru недалеко. А отказаться уже нельзя, вон сколько инвестиций вложено, одни коврики и тонировка чего стоят, а лифт подвески, это что, все напрасно было? Вот и приходится продолжать вкладываться в "развитие". Точно так-же с AI - решаем одну проблему (и то не факт), параллельно получаем 10 принципиально новых.
А ведь сначала были радужные мечты веселой поездки в Сочи или на Байкал, и прочие поездки в леруа за евроштакетником, личная свобода и все такое :) И что можно будет лишь агентами повелевать, а они тебе и код, и автотесты и в Confluence Release Notes пропишут и даже в JIRA сами за тебя Done будут нажимать.
1) В современном мире 16-битный int имеет смысл лишь в мире avg-gcc и подобных микроконтроллеров. При этом там парни настолько суровы, что имеют флаг -mint8, который делает int 8-битным, а long long - 32-битным. В реальности же там настолько свой отдельный мир-песочница, что их библиотечный код практически никак не пересекается с кодом из мира POSIX, т.е. все эти микроконтроллеры можно просто исключить в отдельный класс: даже MQTT библиотеки там приходится иметь строго свои отдельные, особым образом оптимизированные.
2) Объективно мир стремится к унификации. big-endian платформы практически все вымерли, кодировки, отличные от UTF-8 - доживают последние годы. 32-битные варианты Windows, Linux, Android, iOS и прочих macOS уже существуют скорее как музейные экспонаты, пополнив полки с DOS, CP/M и PDP-11. Аналогично весь мир довольно скоро придет к некому гомеостазу, где при разработке ПО int будет везде 32-битным, а long - 64-битным. Причина - банальные автотесты, никому не хочется возиться с экзотическими или устаревшими платформами (а с Windows в особенности)
3) int32_t, int64_t - хорошая попытка, но нет, просто в виду гигатонн открытого кода (glibc и далее), который в API вместо них продолжает использовать int. Гарантию можно всегда достичь через static_assert(sizeof(int)==4). И static_assert(sizeof(long)==8), как способ окончательно удалить Windows из Jenkins фабрики :) Впрочем, на long свет клином не сошелся и в реальности его почти никто непосредственно не использует, предпочитая алиасы вроде size_t
4) Xто характерно - почти нигде в API не применяется непосредственно и long long, это странное LLP64 наследие из мира Windows создало кратно больше проблем, чем решило.
5) А вот 64 битный беззнаковый size_t - это увы, уже необратимый инженерный просчет века. В реальности он такой не нужен, хватило бы 32-битного и знакового int для практически всех случаев, где применяется size_t (знаковость нужна для избежания ошибок вычислений при манипуляциях). Современные компьютеры могут адресовать лишь до 48-бит (до 52 или 56 бит через спецоборудование), и до сих пор никому как-то не потребовалось создать hashmap размером с >128 терабайт. Да даже более 32 гигабайт: hashmap или вектор с элементом уже в 8 байт просто физически не сможет задействовать более 32 бит индекса, так, чтоб оставаться в RAM, а не свопиться на диск.
Т.е. реальных строковых или контейнерных данных, которые требуют более 2 миллиард индексов для доступа к своему элементному типу через for (i = 0; i < N; i++) / foreach - в реальности попросту не существует. Даже MKV фильмы это не сплошной поток байт, а набор независимых между собой структурированных чанков размером примерно по 5М каждый. CSV файлы с дампом баз данных - это тоже набор строк (чанков), их нет смысла рассматривать иначе, как поток отдельно независимых строк. Любые файлы в облачных хранилищах также в реальности хранятся чанками, из соображений репликаций и бекапов. Т.е. декларируя size_t size мы практически всегда закладываем как минимум два байта потерь из 8. А в реальности почти всегда теряются сразу 5 или 6 байт из 8 в size_t полях - там практически всегда будут нули. А LEB128 или подобное почти никто не применяет даже для хранимых на дисках данных, зачем, если можно сразу в size_t хранить размеры строк вроде названий городов и улиц.
6) При этом к 64-битному off_t, как и к pointer - конечно вопросов нет, адрес или смещение не есть размеры сущности, адрес может быть произвольным и произвольно большим, особенно в аспектах виртуальной памяти. Ну, за исключением того, что в чудном мире Windows LLP64 и off_t не такой как все, а 32-битный :)
7) А еще про неявно знаковый char против неявно беззнакового char не поговорили, но это уже совсем другая история.
Справедливости ради - OS/2 не была альтернативой Win'95. Она не умела запускать win32 приложения, только win16 и DOS. Хотя вытесняющей многозадачностью приложения DOS через VDM вполне стабильно на 386 железе умела запускать уже Windows 3.11, но считалось, что OS/2 это делает лучше - последнюю довольно массово применяли для организации всяких FIDO BBS серверов с кучей модемов, пока все массово не перешли на FreeBSD с ее UUCP, а потом и вовсе на TCP/IP с Cisco и прочим.
А вот реальной стабильной альтернативой Win'95 была Windows NT 4.0, очень достойный продукт своего времени, который мог запускать вытесняющей многозадачностью и DOS, и win16 и само собой win32, если в наличии были 16MB+ RAM (их можно было далеко не во всякую материнку того времени вставить)
Насколько я знаю нет, там все достаточно предсказуемо в linux, при уровне 2. Обещают правда совсем полную рандомизацию, но пока это лишь в теории. Большим сюрпризом там скорее магическое число 89TB, которое есть суть PIE base 0x555555554000, но оно лишь дополняет правило: не первый терабайт и не последний 128й, а да, и 89-й тоже трогать нельзя :)
40TB это я рубанул "от души" :) Но скорее с целью показать пределы масштабируемости. Считается же что 64 бит это прям очень много (18.4 экзабайт), а в реальности намного скромнее, 48 бит в общем случае, или 52/56 бит в особо крутых серверных материнках.
Но основная идея да, заключается в том, что с 64 битами адреса и возможностью манипуляций с mmap(MAP_FIXED) многие старые парадигмы управления памятью из 16-, 31-, 32- битных миров из 70-х годов как минимум могут быть пересмотрены. К примеру можно играть в арены (region memory aka memory pools), с заданными циклами жизни, и не заниматься мелкодробным free() / delete - т.е. вместо malloc() / new выделять память, просто последовательно сдвигая HWM в заранее отмпаленном регионе, прям как в Java, и лишь в конце жизненного цикла (внешнего вызова, сессии, процесса) - просто удалять этот регион целиком. Внешние ресурсы (хендлы) - собирать в linked list и удалять вместе с регионом. Про деструкторы и вовсе забыть. Идея кстати не нова, вовсю используется в APR / apache httpd и PostreSQL, образцах long-running стабильности. В виде плюшки заодно и от memory reuse с undefined behavior проблем избавиться.
Реализацией пока не поделюсь, это отдельный исследовательский проект, думаю в следующем году выложить в github/MIT. Правда вопросами кольцевых буферов в аспекте непрерывной группы чанков я не озадачивался, пока не было необходимости. Пока там в части кольцевых буферов пока лишь аналог LMAX Disruptor для сверхскоростной межпроцессной IPC на lockfree алгоритмах. Для меня самого было удивительным, что даже в offset pointer на самом деле уже и не особо надо, если для всех изолированных процессов заранее замапить буфер в строго определенный адрес - так все процессы будут иметь единую сквозную адресацию.
Суть статьи: не пытайтесь в самописную JIRA, лучше купите наше решение и поддержку.
Статья как минимум небесполезна уже тем, что можно озадачиться вопросом и внезапно найти уже готовые Plane, Redmine или Worklenz.
И для замены ServiceNow оказывается уже существуют FreeITSM, iTop, GLPI - т.е. все давно изобретено до вас, для AI/PET проектов тема управления IT процессами точно не годится.
И платформ LowCode в последнее время тоже появилось десятки разных, еще одна скорее всего никому не нужна.
А еще можно вспомнить про LowСode платформу 1С, где тоже можно очень быстро создать конфигурацию для импортозамещения JIRA и ServiceNow :)
Озвученная проблема: а) нужно иметь писателя и иметь читателя(лей) для потоковых данных, приближенных к realtime б) нужно максимально быстро переиспользовать уже прочитанную / обработанную память в) нужно обеспечить непрерывность в памяти нескольких подряд идущих элементов размером в несколько килобайт или мегабайт
Теперь вопрос - а что мешает просто зарезервировать через mmap() (но не выделить) диапазон адресов размером в несколько терабайт (для современных 64-х битных архитектур с 48 реальными адресуемыми битами верхний предел около 128 терабайт, в реальности чуть менее). Физическая память будет выделяться (commit) при записи. Уже обработанную память - просто освобождать через madvise(MADV_DONTNEED). Быстрее в этом мире ничего нет, т.к. malloc()/free()/new/delete это просто обертки над mmap() с его commit on demand
80TB это примерно 80млн чанков размером по 1MB. А при достижении "верхнего предела" можно просто взять паузу и сделать remap() активной часть буфера в начало.
Не просто так конечно - там уже нужно будет две последовательно очень большие области, скажем по 40TB. И если наш читающий хвост переехал из первой области во вторую (т.е. первая стала полностью не нужна), то мы быстро первую отмпаливаем целиком, вторую ставим на место первой через mremap(), и еще раз делаем заново mmap() второй области с MAP_FIXED.
Linux довольно консервативен в части использования диапазонов адресов - все что не первый и не последний терабайт из адресуемых 128TB userspace - это система практически не задействует сама (heap растет снизу вверх, стек и mmap()ы без указания адреса - сверху вниз).
Абсолютно все 3D реализации по факту давали намного худшее качество картинки. Для вау-эффекта ок, один, ну два раза посмотреть. Но даже аватар в 3D, в кинотеатре - смотрится просто ужасно в сравнении с 2D. И мутно, и цветопередача хуже, и глаза потом полдня болят.
По аналогичным причинам и VR шлемы провалились - да, как вау эффект прикольно, но постоянно в них работать или даже фильмы иногда смотреть - просто некомфортно.
а убедиться, что это работает в реальности во всех нужных и ненужных сценариях, по-прежнему может только человек.
Там другое забавнее. Если SDD промпт чуть более двух листов и генерируемый бандл больше условных 50к, то начинается веселая игра вида "уточняем вот тут требования или пытаемся исправить поведение, в результате вот тут вроде как чинится, но внезапно ломается в других местах, и даже там, где не просили; чиним уже там - ломается тут уже то, что собирались чинить изначально, в результате идем думать как все-таки завтра описать новые требования в SDD спеке, чтоб не сразу много поломалось на следующий день, а в конце недели решаем, что проще плюнуть и вернуться к ручному кодированию с явным контролем границ изменений".
На собственных PET и не только PET проектах - через AI очень легко сделать POC / MVP с целью оценить идею в принципе, пусть даже это будет полурабочий прототип UI для A/B, но на нулевом цикле этого достаточно.
Но вот что забавно - запуская один и тот-же промпт / SDD в разные дни - на выходе каждый раз получаешь абсолютно разные результаты, которые даже через meld или winmerge невозможно сравнить, а через git отслеживать изменения уже и вовсе бесполезно, настолько все прыгает хаотичным образом по файлам.
Но десятком подобных SDD итераций в принципе можно приблизиться к более-менее работоспособному результату в один случайный день, а в целом - как минимум продумать и описать вручную (а как еще?) модель данных, осознать-описать ключевые функции в этом самом SDD. В результате будет на выходе формальное ТЗ, которое и для человеков тоже вполне себе полезный документ, и... да, не такой уж и плохой стартовый бандл, даже с какой-то структурой проекта, который как минимум компилируется, запускается, что-то отдаленно похожее на требования из ТЗ делает в рамках заданного стека и прочих ограничений.
И вот на этом вся AI революция и заканчивается, дальше начинаются реалии. Потому что этот бандл без ручных изменений выпускать в продакшин, даже в локальный intranet для каких видавших виды кладовщиков склада готовой продукции - уже в реальности не получится, и все причастные прекрасно знают почему :)
А после ручных изменений дальше весело играть в SDD уже не есть возможно, т.к. каждая новая итерация / генерация безжалостно потрет и все ранее внесенные в код ручные правки, и даже без ручных правок - аннулирует десятки часов "ручного" code-review и/или "ручного" UI-тестирования. Т.е. на этом этапе или возвращаемся обратно на нулевой цикл генерировать очередной POC / MVP, или забираем на баланс старого доброго ручного сопровождения, доработки и тестирования этот самый удачный бандл.
А SDD промпт не выбрасываем - продолжаем иногда запускать его и смотреть, какие новые технологии сейчас в моде, тоже кстати польза.
Практическая необходимость удаленно запускать GUI приложения под xNIX: установка Oracle RDBMS, там интерфейс установщика изначально был на Java Swings. А на серверах не то что видеокарт не было, они и расположены были иногда на другом континенте. Сразу можно было познакомиться и с Exceed, XMing, Cygwin и ssh X11 forwarding еще в 200х годах, если не раньше.
Да, можно было и в unattended install в TUI, но там было просто неудобно.
Аналогично можно-нужно было запускать всякие IDE на удаленных серверах, Solaris Studio, Netbeans, еще задолго до появления VS Code Remote.
В современных реалиях это все правда уже не сильно нужно, более актуальным является x2go, там есть режим отключиться-переподключиться к удаленному рабочему столу, прям как изначально в RDP/Citrix ICA.
В случае X11/XDCMP отключение приводило к отстрелу всех приложений сессии by design, но могу ошибаться, возможно уже доработали.
Обсуждать можно что угодно, тем более в рамках concept sanity check.
Но про mmap() не понял.
Замапить файл размером (там size_t параметр) более 2/4 гигабайт - да, этим пожалуй можно найти оправдание 64-х битному size_t. Можно ли иметь файл размером более 2/4 гигабайт - аналогично, конечно можно. Но тут тонкий момент - эти сущности относятся к другому классу памяти - это уже не RAM, а persistent memory.
Изначально меня интересовали размеры контейнеров в RAM, в частности размеров строк (Strings), и зачем их определять как size_t. Именно с позиций практического аспекта, как пример из реальной задачи где есть строки или какой ArrayList количеством символов (элементов) более 2млрд.
А с размерами именно файлов скорее терминологическая путаница, т.к. их размер это фактически верхний предел адресуемого смещения хранилища данных, aka file data offset limit, т.е. off_t и size_t тут по сути одно и тоже, и работают одинаково, и возможно оба просто изначально имеют неудачное название.
void *mmap(size_t length; void addr[length], size_t length, int prot, int flags, int fd, off_t offset);
Хотя открыв ptrdiff_t, uintptr_t, а также ssize_t - можно пожалуй констатировать, что с удачными названиями и в целом с концепциям в стандартах некоторое фиаско, впрочем, об этом изначально речь и шла, в утверждении что size_t - это инженерный просчет.
Возможно лучшим решением было бы иметь size64_t в дополнение к существующему off64_t
Или просто использование int для строк и тех самых контейнеров по типу ArrayList / vector - последнее наиболее ожидаемое поведение и наиболее оптимальное в части cache friendly - банально больше данных помещается в кэш CPU, меньше промахов и т.д..
ООК, фото панорама на 2 терапикселя. Но какой практический смысл даже на этом примере иметь 64 битный size_t?
Даже подобные "картинки" все равно внутри нужно дробить на чанки и отдельно их компрессировать и по отдельным индексированным в каталоге offset хранить (естественно 64 битным). Иначе распаковка solid архива 12 терабайт со скоростью 485MB/s (lossless qoi компрессия) займет около 8 часов (или 3 дня, если в JPEG XL).
offset это не size
В текущих реалиях это не имеет практического смысла. Хотя и утверждается (кем?), что рынок мейнфреймов растет (хотя рынок HP/UX, SPARC, AIX наоборот который год активно замещается на x64/AArch64 Linux решения, парадокс), это слишком специализированная, нишевая архитектура, тем более для OSS и прочих импортозамещений.
Для меня самого ограничения в 48 бит адреса были весьма неожиданным открытием. Казалось бы - можно делать mmap() based databases / raw files размером до практически неограниченных 18 экзабайт, ан нет, верхний лимит в 128 терабайт, а это сильно меньше, чем возможности современных СХД на НЖМД: что-то вроде 47 петабайт в одной стойке, до 1 экзабайта рекорд в CERN.
Хотя возможность произвольно адресовать 1 экзабайт через mmap() выглядела многообещающей, но нет, вам это не нужно ибо не положено :)
Радует, что начали минусовать и хоть что-то писать.
time_t имеет вполне объективную природу - 32 бита никак не хватало для хранения секунд после 2037 года, эту тему вроде закрыли. А там еще и миллисекунды нужны.
Но давайте еще раз с size_t. Можно привести пример контейнера с данными (из реальных задач), которому требуется более 32-бит для индексации элемента? С поправкой на то, что массив из 8-байтных элементов уже займет 32гигабайта памяти.
Этот пост выше был написан именно для этого - покажите хоть одну задачу, где нужен контейнер в ОЗУ на более чем 2млрд. элементов одновременно. Есть примеры?
Чего именно конец? Что в этом байтовом array хранится? Можно пример? Фотография в raw более 4гибайта? И опять-же, off_t это не size_t. Размер это не смещение и не адрес.
Инвесторы в ИИ бум видимо только начинают подозревать, что AI агенты в реальности не сокращают условно 10 программистов, заменяя их на одного писателя SDD промптов. Скорее наоборот - создают еще 20..30 новых рабочих мест, которые будут пытаться взять под контроль и пытаться развивать эти самые нейрослопы. А старые скучные задачи тоже нужно будет кому-то продолжать пилить.
Это же примерно как покупка автомобиля. Экономика владения ненужным для решения выдуманных задач. Сначала безудержная эйфория и радужные представления о том, как много он, личный автомобиль - проблем решит. А уже на втором цикле владения начинаются рекурсивные проблемы владения: постройки гаража, покупки паркоместа, летне-зимней резины, зимней омывайки, антикора, шумки, выбор навигатора, муки с андроидавто, уроки контраварийного вождения, перепрошивки, глюки, удаления катализатора, проблема пробитой резины, первое знакомство с эвакуатором, первое знакомство с инспектором, а там до exist.ru недалеко. А отказаться уже нельзя, вон сколько инвестиций вложено, одни коврики и тонировка чего стоят, а лифт подвески, это что, все напрасно было? Вот и приходится продолжать вкладываться в "развитие". Точно так-же с AI - решаем одну проблему (и то не факт), параллельно получаем 10 принципиально новых.
А ведь сначала были радужные мечты веселой поездки в Сочи или на Байкал, и прочие поездки в леруа за евроштакетником, личная свобода и все такое :) И что можно будет лишь агентами повелевать, а они тебе и код, и автотесты и в Confluence Release Notes пропишут и даже в JIRA сами за тебя Done будут нажимать.
Да да. Круиз контроль автопилот.
1) В современном мире 16-битный int имеет смысл лишь в мире avg-gcc и подобных микроконтроллеров. При этом там парни настолько суровы, что имеют флаг -mint8, который делает int 8-битным, а long long - 32-битным. В реальности же там настолько свой отдельный мир-песочница, что их библиотечный код практически никак не пересекается с кодом из мира POSIX, т.е. все эти микроконтроллеры можно просто исключить в отдельный класс: даже MQTT библиотеки там приходится иметь строго свои отдельные, особым образом оптимизированные.
2) Объективно мир стремится к унификации. big-endian платформы практически все вымерли, кодировки, отличные от UTF-8 - доживают последние годы. 32-битные варианты Windows, Linux, Android, iOS и прочих macOS уже существуют скорее как музейные экспонаты, пополнив полки с DOS, CP/M и PDP-11. Аналогично весь мир довольно скоро придет к некому гомеостазу, где при разработке ПО int будет везде 32-битным, а long - 64-битным. Причина - банальные автотесты, никому не хочется возиться с экзотическими или устаревшими платформами (а с Windows в особенности)
3) int32_t, int64_t - хорошая попытка, но нет, просто в виду гигатонн открытого кода (glibc и далее), который в API вместо них продолжает использовать int. Гарантию можно всегда достичь через static_assert(sizeof(int)==4). И static_assert(sizeof(long)==8), как способ окончательно удалить Windows из Jenkins фабрики :) Впрочем, на long свет клином не сошелся и в реальности его почти никто непосредственно не использует, предпочитая алиасы вроде size_t
4) Xто характерно - почти нигде в API не применяется непосредственно и long long, это странное LLP64 наследие из мира Windows создало кратно больше проблем, чем решило.
5) А вот 64 битный беззнаковый size_t - это увы, уже необратимый инженерный просчет века. В реальности он такой не нужен, хватило бы 32-битного и знакового int для практически всех случаев, где применяется size_t (знаковость нужна для избежания ошибок вычислений при манипуляциях). Современные компьютеры могут адресовать лишь до 48-бит (до 52 или 56 бит через спецоборудование), и до сих пор никому как-то не потребовалось создать hashmap размером с >128 терабайт. Да даже более 32 гигабайт: hashmap или вектор с элементом уже в 8 байт просто физически не сможет задействовать более 32 бит индекса, так, чтоб оставаться в RAM, а не свопиться на диск.
Т.е. реальных строковых или контейнерных данных, которые требуют более 2 миллиард индексов для доступа к своему элементному типу через for (i = 0; i < N; i++) / foreach - в реальности попросту не существует. Даже MKV фильмы это не сплошной поток байт, а набор независимых между собой структурированных чанков размером примерно по 5М каждый. CSV файлы с дампом баз данных - это тоже набор строк (чанков), их нет смысла рассматривать иначе, как поток отдельно независимых строк. Любые файлы в облачных хранилищах также в реальности хранятся чанками, из соображений репликаций и бекапов. Т.е. декларируя size_t size мы практически всегда закладываем как минимум два байта потерь из 8. А в реальности почти всегда теряются сразу 5 или 6 байт из 8 в size_t полях - там практически всегда будут нули. А LEB128 или подобное почти никто не применяет даже для хранимых на дисках данных, зачем, если можно сразу в size_t хранить размеры строк вроде названий городов и улиц.
6) При этом к 64-битному off_t, как и к pointer - конечно вопросов нет, адрес или смещение не есть размеры сущности, адрес может быть произвольным и произвольно большим, особенно в аспектах виртуальной памяти. Ну, за исключением того, что в чудном мире Windows LLP64 и off_t не такой как все, а 32-битный :)
7) А еще про неявно знаковый char против неявно беззнакового char не поговорили, но это уже совсем другая история.
Справедливости ради - OS/2 не была альтернативой Win'95. Она не умела запускать win32 приложения, только win16 и DOS.
Хотя вытесняющей многозадачностью приложения DOS через VDM вполне стабильно на 386 железе умела запускать уже Windows 3.11, но считалось, что OS/2 это делает лучше - последнюю довольно массово применяли для организации всяких FIDO BBS серверов с кучей модемов, пока все массово не перешли на FreeBSD с ее UUCP, а потом и вовсе на TCP/IP с Cisco и прочим.
А вот реальной стабильной альтернативой Win'95 была Windows NT 4.0, очень достойный продукт своего времени, который мог запускать вытесняющей многозадачностью и DOS, и win16 и само собой win32, если в наличии были 16MB+ RAM (их можно было далеко не во всякую материнку того времени вставить)
Насколько я знаю нет, там все достаточно предсказуемо в linux, при уровне 2. Обещают правда совсем полную рандомизацию, но пока это лишь в теории.
Большим сюрпризом там скорее магическое число 89TB, которое есть суть PIE base 0x555555554000, но оно лишь дополняет правило: не первый терабайт и не последний 128й, а да, и 89-й тоже трогать нельзя :)
40TB это я рубанул "от души" :) Но скорее с целью показать пределы масштабируемости. Считается же что 64 бит это прям очень много (18.4 экзабайт), а в реальности намного скромнее, 48 бит в общем случае, или 52/56 бит в особо крутых серверных материнках.
Но основная идея да, заключается в том, что с 64 битами адреса и возможностью манипуляций с mmap(MAP_FIXED) многие старые парадигмы управления памятью из 16-, 31-, 32- битных миров из 70-х годов как минимум могут быть пересмотрены. К примеру можно играть в арены (region memory aka memory pools), с заданными циклами жизни, и не заниматься мелкодробным free() / delete - т.е. вместо malloc() / new выделять память, просто последовательно сдвигая HWM в заранее отмпаленном регионе, прям как в Java, и лишь в конце жизненного цикла (внешнего вызова, сессии, процесса) - просто удалять этот регион целиком. Внешние ресурсы (хендлы) - собирать в linked list и удалять вместе с регионом. Про деструкторы и вовсе забыть. Идея кстати не нова, вовсю используется в APR / apache httpd и PostreSQL, образцах long-running стабильности. В виде плюшки заодно и от memory reuse с undefined behavior проблем избавиться.
Реализацией пока не поделюсь, это отдельный исследовательский проект, думаю в следующем году выложить в github/MIT. Правда вопросами кольцевых буферов в аспекте непрерывной группы чанков я не озадачивался, пока не было необходимости. Пока там в части кольцевых буферов пока лишь аналог LMAX Disruptor для сверхскоростной межпроцессной IPC на lockfree алгоритмах. Для меня самого было удивительным, что даже в offset pointer на самом деле уже и не особо надо, если для всех изолированных процессов заранее замапить буфер в строго определенный адрес - так все процессы будут иметь единую сквозную адресацию.
И т.д. :)
Суть статьи: не пытайтесь в самописную JIRA, лучше купите наше решение и поддержку.
Статья как минимум небесполезна уже тем, что можно озадачиться вопросом и внезапно найти уже готовые Plane, Redmine или Worklenz.
И для замены ServiceNow оказывается уже существуют FreeITSM, iTop, GLPI - т.е. все давно изобретено до вас, для AI/PET проектов тема управления IT процессами точно не годится.
И платформ LowCode в последнее время тоже появилось десятки разных, еще одна скорее всего никому не нужна.
А еще можно вспомнить про LowСode платформу 1С, где тоже можно очень быстро создать конфигурацию для импортозамещения JIRA и ServiceNow :)
Озвученная проблема:
а) нужно иметь писателя и иметь читателя(лей) для потоковых данных, приближенных к realtime
б) нужно максимально быстро переиспользовать уже прочитанную / обработанную память
в) нужно обеспечить непрерывность в памяти нескольких подряд идущих элементов размером в несколько килобайт или мегабайт
Теперь вопрос - а что мешает просто зарезервировать через mmap() (но не выделить) диапазон адресов размером в несколько терабайт (для современных 64-х битных архитектур с 48 реальными адресуемыми битами верхний предел около 128 терабайт, в реальности чуть менее). Физическая память будет выделяться (commit) при записи. Уже обработанную память - просто освобождать через madvise(MADV_DONTNEED). Быстрее в этом мире ничего нет, т.к. malloc()/free()/new/delete это просто обертки над mmap() с его commit on demand
80TB это примерно 80млн чанков размером по 1MB. А при достижении "верхнего предела" можно просто взять паузу и сделать remap() активной часть буфера в начало.
Не просто так конечно - там уже нужно будет две последовательно очень большие области, скажем по 40TB. И если наш читающий хвост переехал из первой области во вторую (т.е. первая стала полностью не нужна), то мы быстро первую отмпаливаем целиком, вторую ставим на место первой через mremap(), и еще раз делаем заново mmap() второй области с MAP_FIXED.
Linux довольно консервативен в части использования диапазонов адресов - все что не первый и не последний терабайт из адресуемых 128TB userspace - это система практически не задействует сама (heap растет снизу вверх, стек и mmap()ы без указания адреса - сверху вниз).
Абсолютно все 3D реализации по факту давали намного худшее качество картинки. Для вау-эффекта ок, один, ну два раза посмотреть. Но даже аватар в 3D, в кинотеатре - смотрится просто ужасно в сравнении с 2D. И мутно, и цветопередача хуже, и глаза потом полдня болят.
По аналогичным причинам и VR шлемы провалились - да, как вау эффект прикольно, но постоянно в них работать или даже фильмы иногда смотреть - просто некомфортно.
Там другое забавнее. Если SDD промпт чуть более двух листов и генерируемый бандл больше условных 50к, то начинается веселая игра вида "уточняем вот тут требования или пытаемся исправить поведение, в результате вот тут вроде как чинится, но внезапно ломается в других местах, и даже там, где не просили; чиним уже там - ломается тут уже то, что собирались чинить изначально, в результате идем думать как все-таки завтра описать новые требования в SDD спеке, чтоб не сразу много поломалось на следующий день, а в конце недели решаем, что проще плюнуть и вернуться к ручному кодированию с явным контролем границ изменений".
На собственных PET и не только PET проектах - через AI очень легко сделать POC / MVP с целью оценить идею в принципе, пусть даже это будет полурабочий прототип UI для A/B, но на нулевом цикле этого достаточно.
Но вот что забавно - запуская один и тот-же промпт / SDD в разные дни - на выходе каждый раз получаешь абсолютно разные результаты, которые даже через meld или winmerge невозможно сравнить, а через git отслеживать изменения уже и вовсе бесполезно, настолько все прыгает хаотичным образом по файлам.
Но десятком подобных SDD итераций в принципе можно приблизиться к более-менее работоспособному результату в один случайный день, а в целом - как минимум продумать и описать вручную (а как еще?) модель данных, осознать-описать ключевые функции в этом самом SDD.
В результате будет на выходе формальное ТЗ, которое и для человеков тоже вполне себе полезный документ, и... да, не такой уж и плохой стартовый бандл, даже с какой-то структурой проекта, который как минимум компилируется, запускается, что-то отдаленно похожее на требования из ТЗ делает в рамках заданного стека и прочих ограничений.
И вот на этом вся AI революция и заканчивается, дальше начинаются реалии. Потому что этот бандл без ручных изменений выпускать в продакшин, даже в локальный intranet для каких видавших виды кладовщиков склада готовой продукции - уже в реальности не получится, и все причастные прекрасно знают почему :)
А после ручных изменений дальше весело играть в SDD уже не есть возможно, т.к. каждая новая итерация / генерация безжалостно потрет и все ранее внесенные в код ручные правки, и даже без ручных правок - аннулирует десятки часов "ручного" code-review и/или "ручного" UI-тестирования.
Т.е. на этом этапе или возвращаемся обратно на нулевой цикл генерировать очередной POC / MVP, или забираем на баланс старого доброго ручного сопровождения, доработки и тестирования этот самый удачный бандл.
А SDD промпт не выбрасываем - продолжаем иногда запускать его и смотреть, какие новые технологии сейчас в моде, тоже кстати польза.
Практическая необходимость удаленно запускать GUI приложения под xNIX: установка Oracle RDBMS, там интерфейс установщика изначально был на Java Swings. А на серверах не то что видеокарт не было, они и расположены были иногда на другом континенте. Сразу можно было познакомиться и с Exceed, XMing, Cygwin и ssh X11 forwarding еще в 200х годах, если не раньше.
Да, можно было и в unattended install в TUI, но там было просто неудобно.
Аналогично можно-нужно было запускать всякие IDE на удаленных серверах, Solaris Studio, Netbeans, еще задолго до появления VS Code Remote.
В современных реалиях это все правда уже не сильно нужно, более актуальным является x2go, там есть режим отключиться-переподключиться к удаленному рабочему столу, прям как изначально в RDP/Citrix ICA.
В случае X11/XDCMP отключение приводило к отстрелу всех приложений сессии by design, но могу ошибаться, возможно уже доработали.