Архитектура NAND флеш-памяти
Массив NAND флеш-памяти состоит из последовательности блоков. Каждый блок состоит из страниц. Страницы состоят из ячеек памяти (транзисторов). Страницы сопоставимы с секторами HDD.
Блок - наименьшая секция стирания в NAND флеш-памяти.
Страница - наименьшая секция записи и чтения в NAND флеш-памяти.
Организация 8GB (64Gbit) 25nm IMFT (Intel-Micron) 2-bit MLC NAND флеш-памяти:
Размер страницы: 8KB
Количество страниц на блок: 256
Размер блока: 2048KB
Количество блоков: 4096
Размер плоскости: 2048 блоков
Количество плоскостей: 2
Характеристики массива:
Произвольное чтение страницы: 50 микросекунд
Программирование страницы: 1300 микросекунд
Стирание блока: 3 миллисекунды
Стирание блока занимает почти в два с половиной раза больше времени, чем программирование страницы.
Расшифровка маркировок Micron/Intel:
На рисунке выше изображёна NAND-микросхема накопителя Patriot Pyro 120GB. Расшифруем номенклатуру микросхемы:
Micron 29F64G08CBAAA WP _ A
Первый ряд | |
29F | NAND флеш-память |
64G | Ёмкость: 64G - 64Gbit; 128G - 128Gbit; 256G - 256Gbit; 512G - 512Gbit |
08 | Разрядность шины: 08 - 8 bit |
C | Бит/Ячейка: С - 2 bit |
B | Кристаллов в микросхеме: B - 1; С,D,E,F - 2; H,J,K,L,M - 4; P,Q,R,T,U - 8 |
A | Рабочее напряжение: A - 3.3V, 3.3V; C - 3.3V, 1.8V |
A | Набор функциональных возможностей: A - Первый набор функциональных возможностей |
A | Интерфейс: A - Только асинхронный; B - Синхронный/асинхронный |
Второй ряд | |
WP | Код корпуса: WP - 48-контактный TSOP (CPL) (Без свинца) |
-Пусто | Показатель скорости (только для синхронного режима): 10 - 200МТ/сек; 12 - 166MT/сек; 15 - 133MT/сек; 20 - 100MT/сек; Пусто - стандартная скорость |
A | Модификация схемы: A - первая; B - вторая |
Одни из микросхем, используемые в OCZ Vertex 3 240GB имеют такую маркировку:
Micron 29F128G08CFAAB WP -12 A
Маркировка микросхем OCZ Agility 3 240 GB:
Micron 29F128G08CFAAA WP _ A
Маркировка микросхем, используемых в ADATA S511 240GB:
Intel 29F16B08CAME1
29F | NAND флеш-память |
16B | Ёмкость: 64G - 64Gbit; 16B - 16Gbytes (128Gbit); 32B - 32Gbytes (256Gbit) |
08 | Разрядность шины: 08 - 8 bit |
C | Кристаллов в микросхеме: A - 1; С - 2; J - 4 |
A | Рабочее напряжение: A - 3.3V (2.7-3.60 V); C - 1.8V (1.7-1.95 V) |
M | Технология изделия: M - MLC NAND флеш-память |
E | Литография: E - 25nm; D - 34nm |
1 | Поколение изделия: 1-9 - Первые поколения |
Определить тип интерфейса Intel NAND флеш-памяти можно по значению напряжения: 'A' - 3.3V - асинхронный; 'C' - 1.8V - синхронный.
Маркировка микросхем, использующихся в Intel SSD 510 250GB:
Intel 29F16B08JAMDD.
OCZ Vertex 3 240GB с микросхемами Intel:
Intel 29F16B08CCME2.
Не обязательно, что в каждой партии конкретная модель будет всегда поставляться с одинаковыми компонентами тех же производителей. Тем не менее, технические характеристики микросхем не должны отличаться.
Стандарты производительности NAND флеш-памяти
Существуют открытые спецификации ONFI, которые определяют скорость интерфейса данных флеш-памяти:
Асинхронный | |
ONFi 1.0: 50 MT/сек | |
Синхронный | |
ONFi 2.0: 133 MT/сек | |
ONFi 2.x: 200 MT/сек | |
ONFi 3.0: 400 MT/сек |
MT/сек - Мегатрансферов в секунду.
Формула скорости передачи данных:
Ширина канала (бит/трансфер) × Трансферов/секунда = Переданных бит/секунда.
Пример. Ширина канала передачи данных NAND флеш-памяти Intel/Micron - 8 бит (1 байт), отсюда, 1 байт × 50 MT/сек = 50 Мегабайт/сек.
Альтернативные спецификации 'Toggle DDR' разрабатывает JEDEC. Samsung и Toshiba выпускают асинхронную Toggle DDR 1.0 NAND флеш-память, которая по производительности приравнивается к ONFi 2.0. Toggle DDR NAND флеш-память не требует синхронизирующего сигнала, этим снижая потребление энергии и упрощая архитектуру чипа.
Скорость интерфейса:
Toggle DDR 1.0: 133MT/сек
Toggle DDR 2.0: 400MT/сек
Контроллеры SSD
Рассмотрим SATA 3.0 6Гбит/сек контроллеры SandForce серии SF-2200. Они являются 8-ми канальными, с шириной канала 8 байт для SF-2281 и 16 байт для SF-2282, с одновременным (параллельным) доступом по всем каналам. Контроллеры SF-2281, и выше, обеспечивают скорости последовательного чтения/записи до 500МБ/сек, и до 166MБ/сек чтения/записи на канал. Особенностью SandForce является сжатие данных в реальном времени и наличие интегрированной в контроллер кеш-памяти. Благодаря хранению эквивалента данных, а не фактических таковых, согласно данным SandForce, установка Windows Vista и Office 2007 занимает 11GB на флеш-памяти, вместо фактических 25GB.
Каждая стрелка символизирует один 8-байтовый канал
Контроллеры Marvell 88SS9174 SATA 3.0 6Гбит/сек также являются 8-ми канальными, не осуществляют сжатие данных "на лету", и в качестве кеш-памяти используют внешний RAM-чип.
Интерливинг флеш-памяти
Несмотря на то, что в контроллере организовано 8-м каналов, в один канал можно включить несколько NAND-устройств (NAND-микросхем). Два NAND-устройства не могут одновременно пересылать данные в одно и тоже время. Что происходит, так это следующее: осуществляется доступ к одному чипу, в то время как другой чип не используется или занят внутренними операциями.
Во время считывания из, или записи в, NAND флеш-память, запись не осуществляется напрямую в страницы, а через промежуточный регистр, который хранит данные, которые поступают из страницы, или в страницу, NAND флеш-памяти. Процесс считывания/программирования является многоступенчатым предприятием, которое не завершается в один такт. Таким образом, можно передать запрос чтения одному NAND-устройству, и далее, в то время как оно получает данные из внутренней страницы, можно отключиться и программировать независимое NAND-устройство в том же канале.
Вследствие такого параллелизма, которое сходное с конвейеризацией, с правильной рабочей нагрузкой и контроллером, который достаточно смышлёный для интерливинга (чередования) операций между NAND-устройствами, 8-ми канальный накопитель, имея 16 NAND-устройств, может превзойти по производительности этот же накопитель с 8-ю NAND-устройствами. Следует заметить, что преимущество не удваивается, так как изначально можно передавать/считывать данные одновременно только в одно устройство, но всё же существует место для незначительного улучшения.
Рассмотрим гипотетический SSD, в котором операция чтения занимает 5 тактов. Имея единственное NAND-устройство на канал, ширину канала 8 байт и отсутствие интерливинга, мы получаем предельную пропускную способность 8 байт для каждых 5 тактов. При большой рабочей нагрузке, после 15 тактовых импульсов, мы бы могли максимально получить с этого NAND-устройства 24 байта данных.
Гипотетический одноканальный SSD, 1 запрос чтения можно выдать через каждые 5 тактов, данные получают на 5-й такт
Опять рассмотрим этот же SSD, с не изменившейся задержкой, но с удвоенным количеством NAND-устройств на канал и задействованным интерливингом. При неизменной рабочей нагрузке, после 15 тактов, мы бы считали 40 байт - прирост 66,6%.
Гипотетический одноканальный SSD, 1 запрос чтения можно выдать через каждые 5 тактов, данные получают на 5-й такт, задействован интерливинг
Данный пример довольно упрощён и предполагает много допущений, но демонстрирует как можно более подходяще использовать один канал с помощью интерливинга (чередования) запросов между несколькими NAND-устройствами.
Аналогичный вид параллелизма применяется внутри отдельного NAND-устройства. Основным преимуществом перехода на тех. процесс 25nm стало увеличение ёмкости NAND флеш-памяти. Таким образом, теперь можно получить устройство ёмкостью 64Gbit только с одним кристаллом ёмкостью 64Gbit. Если требуется ёмкость устройства больше 64Gbit, можно вместить 2 (128Gbit) и 4 (256Gbit) кристалла в одно устройство, с помощью наложения кристаллов друг на друга. Имея несколько кристаллов внутри NAND-устройства, возможно чередовать запросы чтения/программирования также внутри самого устройства. Опять же, мы не получаем двойной или четырёхкратный прирост производительности, так как только один кристалл может передавать данные одновременно, но интерливинг запросов между несколькими кристаллами помогает заполнить любые свободные места конвейера передачи данных, повышая общую производительность.
Принцип чтения/записи
Чтение и запись можно осуществлять в отдельные страницы до тех пор, пока страницы пусты. Тем не менее, после записи в страницу, её нельзя перезаписать. Сначала страницу необходимо стереть, и только после этого можно осуществлять запись снова. И здесь необходимо вспомнить, что наименьшая секция, которую можно стереть в NAND флеш-памяти - это блок. То есть, вы можете считать/записать 8KB за раз, и стереть только 2048KB за раз.
Износоустойчивость флеш-памяти
Каждый раз, когда вы стираете блок, вы уменьшаете срок службы флеш-памяти. Стандартную 25nm MLC NAND флеш-память можно стереть до 3000-5000 раз до того, как она исчерпает ресурс и перестанет сохранять данные.
Из этого следует: 1) вам не следует перезаписывать данные, и 2) вам не следует стирать данные.
Большинство пользователей полностью не заполняют свои накопители, поэтому производители SSD-контроллеров преодолевают такую проблему путём записи в каждую страницу накопителя до момента, когда придется стереть хотя бы один блок.
Записывая всё в каждую страницу ничего не стирая, рано или поздно у вас закончатся свободные страницы. Хотя ваш накопитель формально не будет полностью заполнен (если вы старательно удаляли файлы в процессе эксплуатации, используя только часть ёмкости вашего накопителя), в конечном счёте каждый блок накопителя будет полон действительными и недействительными страницами.
Другими словами, если вы используете только 60% ёмкости вашего накопителя, не исключено, что 100% пространства было использовано для записи вследствие ежедневного создания/удаления файлов.
Принцип функционирования SSD
Современные операционные системы используют адресацию логических блоков (LBA) - простую схему нумерации блоков данных на HDD и SSD, начиная нумерацию блоков с LBA 0. Каждому сектору HDD присваивается свой LBA. Когда вы сохраняете файл, Windows выдаёт команду сохранения этого файла в конкретный адрес логического блока, например LBA 100.
ОС знает какие LBA свободны и какие заняты. При удалении файла, все LBA, которые указывают на этот файл в накопителе, регистрируются как доступные. Данные, которые были удалены, в действительности не были стёрты и не стираются до момента фактического перезаписывания этих секторов.
SSD функционируют похожим образом.
Уровень преобразования флеш-памяти (Flash Translation Layer) в SSD-контроллере сопоставляет LBA со страницами накопителя. Следующая таблица объясняет, что происходит с данными в SSD в зависимости от действия в операционной системе:
Действие в ОС | Ответное действие в HDD | Ответное действие в SSD |
Создать файл | Запись в сектор | Запись в страницу |
Перезаписать файл | Запись новых данных в этот же сектор | Если возможно, то записать в свободную страницу, если нет, то стереть блок и записать в эту же страницу |
Удалить файл | Нет действия | Нет действия |
При удалении файла в операционной системе, HDD и SSD никак на это не реагируют. Ответное действие происходит в случае перезаписи сектора HDD или страницы SSD, и тогда уже вы теряете предыдущие данные. Программы восстановления данных используют эту особенность в свою пользу, и вот каким образом помогают вам восстановить удалённые файлы.
Основное различие между HDD и SSD, тем не менее, это то, что происходит при перезаписывании файла. В то время как HDD может легко записывать новые данные в тот же сектор, в свою очередь, SSD выделит новую (или до этого использовавшуюся) страницу для перезаписываемых данных. Страница, теперь которая содержит недействительные данные, будет просто помечена как недействительная и в определенный момент будет стёрта.
Причина падения производительности SSD
Чтобы воссоздать пример из реального мира, создадим свой собственный SSD с такими тех. характеристиками:
Гипотетический SSD | |
Размер страницы: | 4KB |
Размер блока: | 5 страниц (20KB) |
Ёмкость: | 1 блок (20KB) |
Скорость чтения: | 2KB/сек |
Скорость записи: | 1KB/сек |
Вначале сохраним на него текстовый документ размером 4KB. Запрос поступает в контроллер, который определяет, что все страницы пусты и записывает текстовый документ в первую страницу.
Гипотетический SSD. Синие прямоугольники символизируют пустые страницы
Теперь сохраним JPEG-файл размером 8KB. Запрос опять поступает в контроллер, который заполняет изображением следующие две страницы, которые к счастью пусты.
Операционная система сообщает, что 60% накопителя заполнено. Три из пяти доступных страниц заполнены данными и оставшиеся две страницы пусты.
Предположим, нам нужно удалить текстовый файл. Запрос даже не поступает в контроллер, который уведомлен о наличии трёх действительных страниц и двух пустых.
В завершении сохраним JPEG-файл размером 12KB, для которого необходимо три 4KB-страницы. ОС знает, что первый LBA, отведённый для текстового документа размером 4KB, можно перезаписать. Поэтому, ОС сообщает контроллеру, что этот LBA можно перезаписать и также можно сохранить остальные 8KB изображения в последние свободные LBA.
В то время как запросы поступают в контроллер SSD, теперь возникает проблема. Поступают запросы на запись трёх страниц, но только две страницы свободны. Вспомните, что ОС знает о доступности свободных 12KB, но в накопителе фактически доступны 8KB, и 4KB заняты недействительной страницей. Чтобы завершить запрос на запись, нужно стереть недействительную страницу.
Вспомните, даже если нужно стереть всего одну страницу, то это сделать нельзя; нельзя стереть страницы, только блоки. Придется стереть все данные только для того, чтобы избавится от недействительной страницы, и потом записать все данные обратно.
Для этого нужно считать весь блок в какую-нибудь память - в кеш-память, интегрированную в контроллер, или во внешний кеш (шаги 1 и 2). Считав блок, его можно изменить, удалить недействительную страницу и заменить эту страницу нужными данными (шаги 3 и 4). Но это всё происходит в, одной из двух, кеш-памяти. Теперь нужно записать блок на флеш-память. Имея все данные в кеш-памяти, можно стереть блок флеш-памяти целиком и записать новый блок (шаг 5).
Теперь осознаем что происходит. ОС знает, что нам нужно записать 12KB, которые и были удачно записаны. Тем не менее, контроллер SSD знает, что на самом деле произошло. Чтобы записать 12KB данных, сначала пришлось считать 12KB и затем записать блок целиком, или 20KB.
Наш SSD довольно медленный, он может только записать 1KB/сек и считать 2KB/сек. Запись 12KB должна была занять только 12 секунд, но поскольку сначала пришлось считать 12KB, а потом записать 20KB, операция полностью заняла 26 секунд.
Для пользователя казалось бы, что скорость записи упала с 1KB/сек до 0.46KB/сек, так как запись 12KB заняла 26 секунд.
Вот почему большинство SSD становятся медленнее, чем дольше вы их используете, и также вот почему скорость записи наиболее падает, в то время как скорости чтения, в значительной степени, остаются неизменными. Запись в пустую страницу выполняется быстро, но так как запись в страницу, которая содержит данные, требует дополнительных операций, падение производительности в действительности происходит во время записи, но не во время чтения.
Зарезервированное пространство (over-provisioning)
Одним из подходов противодействия падению производительности SSD является резервирование свободного пространства на SSD. Предположим, наш SSD объемом 20KB в действительности снабжен 24KB-ами флеш-памяти. Зарезервированные 4KB могут быть использованы контроллером. Каким образом?
Вернемся к эпизоду когда нам надо было записать 12KB данных на накопитель, но доступно было всего 8KB в свободных страницах и 4KB в недействительной странице. Для записи 12KB данных пришлось выполнить операцию 'чтения-изменения-записи', которая заняла вдвое больше времени, чем должна длиться запись 12KB.
Если бы было доступно дополнительных 4KB пространства, наша запись 12KB произошла бы без проблем:
8KB были бы записаны на флеш-память, доступную пользователю, а оставшиеся 4KB - в зарезервированное пространство. Скорость записи по прежнему соответствовала бы 1KB/сек, и всё в мире было бы в порядке.
Теперь, тем не менее, если бы мы удалили и пытались записать 4KB данных, мы бы столкнулись с той же проблемой снова.
Чем больше зарезервированного пространства с которым поставляется накопитель, тем дольше производительность будет оставаться на предельном уровне и тем ниже будет коэффициент усложнения записи.
Зарезервированное пространство используется как пул свободных блоков для замены неочищенных и изношенных блоков, и для распределения износа.
Можно собственноручно увеличить суммарный размер зарезервированного пространства. Для этого необходимо выполнить безопасное уничтожение данных накопителя (Secure Erase) с помощью HDDErase (версия выше 3.3 не совместима с Intel SSD) или ПО производителя (напр. Intel SSD Toolbox). После выполнения Secure Erase, создайте на SSD раздел, который будет меньше изначального доступного пространства на SSD. Насколько меньшим создавать раздел? - По вашему усмотрению.
Команда TRIM
Мы сталкиваемся с проблемой падения производительности, в первую очередь, из-за того, что накопитель не знает когда файл удаляется, знает только когда файл перезаписывается. Вследствие, мы теряем производительность за счет выполнения молниеносных операций удаления во время записи нового файла.
Существует команда, о которой многие знают, TRIM. Для функционирования TRIM нужна соответствующая ОС (Windows 7 и выше) и поддержка команды накопителем. Команда эффективно позволяет операционной системе уведомлять SSD когда стирать недействительные страницы до того, как в них будет произведена перезапись.
Процесс осуществляется таким образом:
Во время удаления файла, ОС посылает команду TRIM контроллеру SSD относительно того, какие LBA занимает файл. Далее контроллер копирует блок в кеш-память, стирает удалённые страницы, и записывает новый блок вместе со свежеочищенными страницами на накопитель.
Теперь когда вы будете записывать файл в этот блок, у вас будут пустые страницы, доступные для записи, и ваша производительность записи будет приближаться к уровню, на котором запись и должна быть.
Возвращаясь к примеру в предыдущем, вот что бы произошло, если бы операционная система и накопитель поддерживали команду TRIM:
Шаг 1: Сохранение 4KB текстового файла, который записывается в новую страницу нового накопителя. Здесь без изменений.
Шаг 2: Сохранение 8KB JPEG-файла. Выделяются две страницы - снова без изменений.
В третьем шаге осуществлялось удаление изначального текстового файла размером 4KB. Так как наш накопитель теперь поддерживает TRIM, при выдаче запроса удаления, накопитель бы считал весь блок, удалил первый LBA и записал этот блок обратно на флеш-память.
Команда TRIM осуществляет принудительную очистку блока до момента записи в него. Очистка блока не является дополнительной задержкой, так как происходит после запроса удаления, а не в момент необходимой записи
В результате накопитель в действительности заполнен на 40%, также насколько и сообщает операционная система. Момент записи 12KB JPEG-файла произойдет на полной скорости. Проблема решена, в некоторой степени.
Хотя команда TRIM будет противодействовать проблеме, она не устранит её. Команду TRIM нельзя осуществить во время перезаписывания файла, например во время сохранения изменений документа. В таких случаях вам все же придется сталкиваться с падением производительности.
Удаление ненужных данных/сборка мусора (garbage collection)
Все SSD снабжены некоторыми алгоритмами очистки NAND-блоков и подготовки их к использованию. Алгоритмы очистки на самом деле не задействуются в то время как накопитель новый, но через несколько дней, недель или месяцев использования, очистка станет неотъемлемой частью его работы.
Пример падения производительности SSD, описанный до этого, довольно обобщителен относительно того, что происходит при записи страницы с данными в блок, который полон действительных и недействительных страниц.
На практике запись осуществляется следующим образом:
Выделяется новый блок, действительные данные копируются в него (включая данные, которые вы собираетесь записать), предыдущий блок отправляется на чистку и впоследствии числиться как полностью стёртый и добавляется в пул чистых блоков. При надобности, чистые блоки выдергиваются из этого пула, наполняются данными, и предыдущие блоки очищаются на месте.
Исследовательская лаборатория IBM в Цюрихе создала наглядную схему относительно того, как работает сборка мусора, и ниже приводится её упрощенный вариант.
Схема изображает как раз то, что и было сказано. Поступает запрос записи, выделяется новый блок, данные записываются в него, вследствие блок добавляется в список использованных блоков. Блоки с наименьшим количеством действительных данных (или с наибольшим количеством недействительных данных) добавляются в расписание удаления ненужных данных (сборки мусора), очищаются и отравляются в пул свободных блоков.
На практике это отображается задержкой записи. Средняя задержка произвольной записи 4-х килобайтовых файлов находиться ниже 1 миллисекунды, но максимальная задержка может быть кратной, приблизительно, 350, то есть 350 миллисекунд. Показатель всё равно ниже таковых механических накопителей, но из-за чего максимальные задержки записи взлетают так высоко? Вследствие вышеупомянутых чистки и реорганизаций. Это редко производит заметный эффект на производительность, но является примером происходящего.
И вот здесь играет роль коэффициент усложнения записи.
Схема выше изображает с другой стороны что происходит во время поступления запроса записи. Для входящей записи используется чистый блок (если доступен). Тем не менее, это не единственная запись которая происходит. В конечном счёте, придется выполнить некоторую сборку мусора, чтобы избежать нехватки свободных блоков. Блок с наибольшим количеством недействительных данных выбирается для чистки; его данные копируются в чистый блок, после чего, предыдущий блок стирается и добавляется в пул свободных блоков. На схеме видно размер данных при запросе записи, но в конечной правой стороне видно сколько данных было в действительности записано, учитывая сборку мусора. Такая разница называется коэффициентом усложнения записи.
Коэффициент усложнения записи (Write Amplification)
Количество данных, которые были записаны на флеш-память, относительно данных, которые проступили с хост-контроллера, называется коэффициентом усложнения записи.
WA = Записанных данных на флеш-память ÷ Данных с хост-контроллера.
Коэффициент усложнения записи равный единице является идеальным. Это значит, что если вы хотели записать 1MB данных, то SSD-контроллер записал ровно 1MB. Коэффициент усложнения записи больший 1 не предпочтителен, но неизбежен. Чем выше коэффициент усложнения записи, тем быстрее накопитель израсходует свой ресурс, и тем ниже будет производительность.
Различие GB и GiB
В маркетинговых целях, все ёмкости накопителей указаны десятичном виде, или в GB (Гигабайтах). Единицей хранения цифровой информации является же GiB (Гибибайт).
1 GB = 10^9 байт = 1 000 000 000 байт.
1 GiB = 2^30 байт = 1 073 741 824 байт.
В Windows, 120GB лихо превращаются в 111,76 GiB.
Физический объём накопителя с 16-ю 8GiB NAND-устройствами - 128GiB. Вычитая из 128GiB 111,76 GiB доступных в Windows, получим зарезервированных 16,24GiB. Конвертируя 111,76 GiB в десятичные единицы хранения, получим маркетинговых 120GB.
Источники:
1) www.anandtech.com/show/2738/1
2) www.anandtech.com/show/2829/1
3) www.anandtech.com/show/4316/ocz-vertex-3-240gb-review/1
4) www.hardocp.com/article/2011/08/07/nand_flash_faces_off_synchronous_vs_asynchronous/1
5) download.micron.com/pdf/numbering/numngnand.pdf
6) www.toshiba.com/taec/Catalog/Line.do?familyid=7&subfamilyid=900116&lineid=1735086
7) www.samsung.com/global/business/semiconductor/products/flash/Products_Toggle_DDR_NANDFlash.html
8) en.wikipedia.org/wiki/Transfer_(computing)
9) en.wikipedia.org/wiki/Gibibyte
10) communities.intel.com/thread/24418?tstart=0
4 комментария:
Спасибо за информацию, было очень познавательно
да, да...хоть и потихоньку устаревает инфа, но для общего представления ооочень полезно!
В строке:
"1 GB = 10^6 байт = 1 000 000 000 байт."
У Вас ошибка, должно быть по-видимому "10^9 байт"
Спасибо, исправил.
Отправить комментарий