[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Php и большой объем данных
Страницы: 1, 2
My Little Lotus
Приветствую дамы и господа.

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

Небольшое отступление. Я новичок в программировании, но любознательность заставляет меня браться за разного рода задачи и однажды у меня вышел спор с коллегой сисадмином, в котором он пока выходит победителем. Я не против если это будет так, я просто хочу знать, что в программировании реально есть слово "невозможно" и сейчас выясняю эту ситуацию для себя.

Теперь собственно сам вопрос. Коллега сисадмин сказал, что в современных реалиях с помощью php кода на стандартных серверах невозможно обрабатывать огромное количество данных, но он мало знает о различных способах оптимизации кода ( в принципе как и я ). Я же решил найти альтернативные способы, но самостоятельно пока получается не очень.

По большому счету нужно сгенерировать числа допустим от 1 до 999999999999 и выгрузить их в любой текстовик. Пока я делаю это в объеме 999999, все получается неплохо, там кода то на 8 строк всего. Но повышая количество нулей в основном конечном числе сервер на котором я пытаюсь это сделать естественно говорит fatal error out of memory. Ожидаемо. Сам текстовик с таким количеством данных тянет на 4-5 гигов.

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

Я думал о том, что возможно стоит использовать задержку между определенным количеством перебора, чтобы дать серверу "выдохнуть", но это не избавляет от проблемы перегруженной памяти. Может быть стоит генерировать по 50 000 - 500 000 чисел и записывать в файл частями, тем самым используя меньший объем памяти но увеличивая сроки вычисления. Т.к. это в основном теория, сроки вычисления не важны, однако чтобы опровергнуть смысл слова "невозможно" это должно быть не 80 лет, пусть сроки будут не 10 секунд и не 10 минут, день, два три дня это не важно. Пусть никто никогда так не сделает, но этот результат тот, который мне нужен и я пока в замешательстве от того, как его можно достичь.

Буду рад совету заядлых программистов, даже если вы посмеетесь над моими начинаниями с высоты своего опыта.
brevis
999999999999 -- это не мало.

Я тебе могу предложить начать постигать эту теорию с такого момента.

Как известно, один ASCII-символ, записанный в файл, занимает 1 байт. Можешь в этом убедиться записав в файл 1, 10, 100, миллион символов и посмотреть его размер.

Отсюда легко заметить, что если записать один ASCII-символ в файл 999999999999 раз, то размер этого файла будет 999999999999 байт, что примерно равно 999,9(9) гигабайт (ну вообще чуть меньше, там же надо на 1024 делить, вроде в гугле это называется Гибибайт). Это если записывать только один символ. А если еще хочешь с переносами строк -- то это еще + 999,9(9) гигабайт smile.gif А вот если записывать всю последовательность, как ты хочешь, то будет "чуть больше". Догадаешься сам на сколько больше? Вот тебе подсказка: Если ты запишешь в файл числа от 1 до 1000 (без переносов), то размер файла будет таким:

1000 единиц + (1000 - 9) десятков + (1000 - 99) сотен + 1 тысяча = 2893 байта.

Сможешь сам посчитать свой случай?

А дальше замеряй сколько времени твоя программа пишет скажем, 1 гигбайт, и сможешь посчитать сколько она будет писать всю последовательность.

Чтобы оперативной памяти хватило, последовательность в памяти хранить не надо.

И напоследок занимательный факт, который показывает различие между величинами.
Если ты заведешь счетчик и каждую секунду будешь его увеличивать, то до миллиона ты досчитаешь за 11.5 дней. А до миллиарда за 32 года.

_____________
Чатик в телеге
My Little Lotus
Цитата (brevis @ 29.10.2020 - 21:29)
999999999999 -- это не мало.

Я тебе могу предложить начать постигать эту теорию с такого момента.

Как известно, один ASCII-символ, записанный в файл, занимает 1 байт. Можешь в этом убедиться записав в файл 1, 10, 100, миллион символов и посмотреть его размер.

Отсюда легко заметить, что если записать один ASCII-символ в файл 999999999999 раз, то размер этого файла будет 999999999999 байт, что примерно равно 999,9(9) гигабайт (ну вообще чуть меньше, там же надо на 1024 делить, вроде в гугле это называется Гибибайт). Это если записывать только один символ.  А если еще хочешь с переносами строк -- то это еще + 999,9(9) гигабайт smile.gif А вот если записывать всю последовательность, как ты хочешь, то будет "чуть больше". Догадаешься сам на сколько больше? Вот тебе подсказка: Если ты запишешь в файл числа от 1 до 1000 (без переносов), то размер файла будет таким:

1000 единиц + (1000 - 9) десятков + (1000 - 99) сотен + 1 тысяча = 2893 байта.

Сможешь сам посчитать свой случай?

А дальше замеряй сколько времени твоя программа пишет скажем, 1 гигбайт, и сможешь посчитать сколько она будет писать всю последовательность.

Чтобы оперативной памяти хватило, последовательность в памяти хранить не надо.

И напоследок занимательный факт, который показывает различие между величинами.
Если ты заведешь счетчик и каждую секунду будешь его увеличивать, то до миллиона ты досчитаешь за 11.5 дней. А до миллиарда за 32 года.

Спасибо за развернутый ответ.

Правильно ли я понял, чтобы сгенерировать до 9999999999 числа, даже используя хорошие серверные мощности и все известные (вам, а не мне) способы оптимизации, а так же разбиение цикла на части по типу от 1 до 100 000 и записать, от 100 000 до 1 000 000 и дописать и тд (чтобы компенсировать недостаток памяти) и выдав самый сверхрезультативный скрипт это будет занимать НЕВЕРОЯТНОЕ КОЛИЧЕСТВО ВРЕМЕНИ и по факту все же невозможно сделать это за обозримо реальный срок?
Гость_chee
My Little Lotus записывать и читать данные из файлов построчно не вариант что-ли? Я чет вообще не понимаю проблемы.
Гость_chee
Цитата (My Little Lotus @ 29.10.2020 - 21:45)
Правильно ли я понял, чтобы сгенерировать до 9999999999 числа, даже используя хорошие серверные мощности и все известные (вам, а не мне) способы оптимизации, а так же разбиение цикла на части по типу от 1 до 100 000 и записать, от 100 000 до 1 000 000 и дописать и тд (чтобы компенсировать недостаток памяти) и выдав самый сверхрезультативный скрипт это будет занимать НЕВЕРОЯТНОЕ КОЛИЧЕСТВО ВРЕМЕНИ и по факту все же невозможно сделать это за обозримо реальный срок?

нет, не правильно, это тупо можно распараллелить. Тогда с этим справится даже raspberry pi.
My Little Lotus
Цитата (Гость_chee @ 29.10.2020 - 21:51)
Цитата (My Little Lotus @ 29.10.2020 - 21:45)
Правильно ли я понял, чтобы сгенерировать до 9999999999 числа, даже используя хорошие серверные мощности и все известные (вам, а не мне) способы оптимизации, а так же разбиение цикла на части по типу от 1 до 100 000 и записать, от 100 000 до 1 000 000 и дописать и тд (чтобы компенсировать недостаток памяти) и выдав самый сверхрезультативный скрипт это будет занимать НЕВЕРОЯТНОЕ КОЛИЧЕСТВО ВРЕМЕНИ и по факту все же невозможно сделать это за обозримо реальный срок?

нет, не правильно, это тупо можно распараллелить. Тогда с этим справится даже raspberry pi.

Распараллелить? Это дополнительные ресурсы какие то? Я никогда не сталкивался с параллельными вычислениями.
Гость_chee
Цитата (My Little Lotus @ 29.10.2020 - 21:59)
Распараллелить? Это дополнительные ресурсы какие то? Я никогда не сталкивался с параллельными вычислениями.

Распараллелить - это взять задачу и распланировать ее запуск на очень много одинаковых процессов, которые будут запущены асинхронно. При том каждому процессу дать свою часть, которую другой процесс не будет выполнять. В итоге вычислительные ресурсы будут утилизированы максимально
My Little Lotus
Цитата (Гость_chee @ 29.10.2020 - 22:15)
Цитата (My Little Lotus @ 29.10.2020 - 21:59)
Распараллелить? Это дополнительные ресурсы какие то? Я никогда не сталкивался с параллельными вычислениями.

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

Спасибо за адекватность на тупой вопрос.

Правильно ли я понял, что распараллелить в моем случае это

script1.php от 1 до 999999
script2.php от 999999 до 99999999
script3.php от 99999999 до 9999999999
и тд

и запустить их одновременно?

Гость_chee
My Little Lotus
да

<?php

$child = false;

if (!empty($argv[1]) && $argv[1] == 'child') {
$child = 1;
}

if ($child) {
$content = '';
for ($i = $argv[2]; $i < $argv[3]; $i++) {
$content .= $i;
}
file_put_contents('out/' . $argv[2] . '-' . $argv[3] . '.txt', $content);
return;
}

$lastX = 0;

for ($x = 10000000; $x <= 9999999999; $x += 10000000) {
exec('php ' . $argv[0] . ' child ' . $lastX . ' ' . $x . ' > /dev/null &');
$lastX = $x;
}
die;


Примерно это выглядит так. Но не запускай это, твой пк придется перезагружать, так как процессор уйдет в 100% загрузку. А также этот скрипт нагенерит файлов в размере 100-120Гигабайт.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.