Мысли и теория

Как ваши данные хранятся на диске и в памяти?

Немного углубившись в то, что происходит под капотом, когда вы манипулируете файлом Excel или фреймами данных.

Я считаю себя прикладным программистом, использую языки программирования высокого уровня, такие как Python, для управления фреймами данных, построения простых конвейеров для облегчения анализа данных определенных задач. Однако на атомарном уровне компьютер сам не понимает, что означает «pandas.read_csv ()» или что на самом деле делает функция «write.table ()». Это заставляет меня задуматься о промежуточных этапах преобразования наших команд в двоичные биты 0/1 и побуждает написать эту статью.

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

утечка памяти? индексирующий файл? накладные расходы на память? Потоковая передача ввода-вывода?

Так что соберитесь с духом и давайте приступим к делу!

Как выглядит диск?

Когда вы находитесь на своем ПК или Mac, вы открываете компьютер или Finder, все файлы, которые появляются там, хранятся на диске, иногда диск также называют хранилищем. В настоящее время почти большинство персональных компьютеров используют твердотельные диски (SSD), однако, чтобы передать некоторую интуицию, я собираюсь использовать жесткий диск (HD), чтобы проиллюстрировать физическую структуру диска.

Структура типичного жесткого диска похожа на проигрыватель компакт-дисков, у него есть рычаг, который может вращаться и переключаться на выбранную дорожку, головка рычага может читать, записывать или стирать данные, хранящиеся на каждой дорожке поверхности.

Поверхность также называется пластиной, и пластина может быть разделена на набор физических единиц, называемых сектором. Между каждым сектором есть промежутки, и несколько секторов составляют блок, блок - это логическая единица.

Если я скажу вам, что одна дорожка на пластине имеет максимальную емкость 1024 КБ (1 МБ), тогда вы знаете, что ваш файл Excel, который, допустим, составляет 2 МБ, будет занимать две пластины, чтобы сохранить его на диске.

Если скорость вращения известна, вы можете легко вычислить, насколько быстро файлы / биты могут быть перенесены с диска в память или наоборот. Также становится ясно, почему большому файлу требуется больше времени для чтения, потому что ему нужно больше времени, чтобы вращать руки, и руки также требуют больше времени для чтения, поскольку область хранения будет больше.

Твердотельный диск (SSD) будет иметь более быстрое время доступа, а архитектура сильно отличается от примера с жестким диском (HD), который я показал вам выше. Но, надеюсь, это может дать вам четкое изображение того, где ваши файлы, и теперь я покажу вам как данные на самом деле лежат на диске.

Как данные распределяются на диске?

В системе управления базами данных (СУБД) каждая запись (запись - это, по сути, строка во фрейме данных) определенным образом лежит на диске для ускорения поиска, вставки и удаления. Представьте, что если каждая запись разбросана по диску без каких-либо правил или организаций, не будет возможности выполнять запрос, индексацию и любые манипуляции.

Проще говоря, вы можете хранить все данные по строкам, что означает, что похожие записи / строки будут собираться вместе. При этом построчное индексирование может быть очень эффективным, поскольку добавление операций по столбцам требует затрат, или же индексирование по столбцам может быть относительно медленным. Если вы пойдете по столбцам, все станет с точностью до наоборот.

Представим, что каждая строка будет храниться в объединенном пространстве на диске, как показано на рисунке. С этой записью связан физический адрес или указатель. В дополнение к этому, ключ поиска обычно используется в качестве прокси в индексном файле. Индексный файл - это в основном пары комбинаций ключа поиска и указателя. Таким образом, наличие ключа поиска позволяет ускорить поиск и избежать накладных расходов. Благодаря наличию ключей поиска ученые разработали широкий спектр эффективных схем для представления и организации всех ключей поиска. Яркие примеры включают:

  1. B + tree: самоуравновешенное дерево с одинаковым расстоянием от корня до всех конечных узлов.
  2. Дерево B: Подобно дереву B +, но его записи хранятся на нелистовых узлах
  3. Расширяемое хеширование: каталог вместе с корзинами, корзинами хранит ключ хеширования, вычисленный с помощью хеш-таблицы или хеш-функции.
  4. Линейное хеширование: Подобно расширяемому хешированию без каталога, но с несколькими уровнями хеш-функций.

Поскольку это не технический блог, я хотел бы порекомендовать вам несколько замечательных видеороликов на YouTube (ссылка выше), в которых объясняется, что такое каждая схема индексации и как они обеспечивают быструю и эффективную вставку и удаление. Но главный вывод из этого раздела заключается в том, что данные размещаются на диске хорошо продуманным образом, что позволяет нам эффективно извлекать их и манипулировать ими.

Как читать байты / файлы с диска в память?

Во-первых, я надеюсь привить небольшой неинтуитивный факт о том, что файл на самом деле является потоком битов / байтов. Когда вы читаете файл в память, вы имеете дело с серией 0/1 и надеетесь правильно загрузить определенную часть файлов.

Теперь нам нужно использовать какой-нибудь низкоуровневый язык, например C:

# declare file pointer
File *fp;
# initialize file pointer with a binary file stored on disk
fp = fopen('./test_file.bin','r');
# set the reading pointer from starting point (SEEK_SET) to 4 bits forward (offset = 4)
fseek(fp,4,SEEK_SET);
# declare a pointer to store the file in memory
ph = (char) malloc(128);
# read the file, read 128 bits to the pointer in memory
fread(ph,sizeof(char),128,fp)
# free the memory
free(ph)

Как показано на рисунке и во фрагменте кода, функция fseek имеет встроенную переменную SEEK_SET, которая является начальной позицией файлового потока. Мы устанавливаем offset=4, чтобы функция считывала с позиции, которая на 4 бита впереди SEEK_SET. Затем мы объявляем указатель на char в памяти, используя функцию fread для специального чтения 128 бит файлового потока в конкретное пространство памяти, которое мы только что определили. Вот как на самом деле работает чтение с диска в память.

Кроме того, не забудьте сначала выделить пространство памяти, используя функцию malloc в C. Также важно освобождать пространство памяти всякий раз, когда вы вручную выделяете пространство раньше, используя функцию free. Игнорирование этого шага может вызвать проблему утечки памяти, которая вызвана неиспользуемой памятью, которая не была правильно освобождена.

Заключение

Как я сказал в начале, в большинстве случаев реализация на низком уровне не является нашей главной заботой как прикладного программиста. Однако я всегда думаю, что это не повод мешать нам немного узнать об основах компьютерной системы. Надеюсь, вы найдете эту статью интересной и полезной, спасибо за внимание! Если вам понравилась эта статья, подпишитесь на меня в среднем, большое спасибо за вашу поддержку. Подключите меня к моему Twitter или LinkedIn, а также дайте мне знать, если у вас есть какие-либо вопросы или какие уроки вы хотели бы видеть в будущем!