Pull to refresh

Comments 83

image
Эта картинка вводит в ступор. Если увеличить размер — уменьшится качество, если увеличить качество — уменьшится размер. Круто, конечно, но как то не правдоподобно.
Еще хотелось бы узнать на счет одинаковых изображений. Если с форматами со сжатием без потерь все ясно — одинаковые файлы можно удалять, а хранить только один, то как быть с форматами со сжатием с потерями? В этом случае с виду одинаковые картинки на самом деле будут разными. Есть ли вообще смысл удалять дубликаты? Например, произошло какое-то глобальное событие — разные пользователи начинают загружать на сервис миллиард одинаковых фото этого события, как быть?
загружать их, просто загрузить будет дешевле и правильнее любых не строких дедубликаций, если я изменил тона на фото это не значит что после загрузки я должен увидеть чужой вариант фотографии. + ошибки в таких алгоритмах.
В лучшем случае можно делать дедубликаю по хешу содержимого файла, она ещё и универсальная
md5 хеш от содержимого файла может помочь решить проблему… Можно отработать и расхождение файлов в принципе… Варианты решениия при необходимости есть.
Подробное описание решения — Статья
Я кстати проверял что быстрее, md5 или sha1, на мелких файлах разницы нету, но sha1 на 8 символов длинее.
На больших файлам sha1 как ни странно быстрее. xeon 1270v3
а пережатие фотографий? Наличие разных тегов? Мне кажется это надежнее habrahabr.ru/post/120562 и быстрее всего

Википедия, кстати умеет ловить дубли.
Пробовал. Идет приличная нагрузка на базу данных (я делал похожим образом) Сравнение делал через базу данных.
Попробуйте найти похожие SQL запросом в базе с парой милионов фоток… довольно ресурсоемко…
И любой алгоритм ошибается. Будет не приятно если при загрузки фото любимой бабушки сайт откажется грузить потому, что похоже на фото чьей то собачки)))) (такое было)
ресурсоемко, если нет особой разнцы. А какой тип таблиц? Но ведь отпечатки пальцев так и ищут. Лимит до 2 сек. с базами в сотню лямов.

Возможно проще раз в месяц прогой десктопной искать дубли. Ежели цель — место.
Ой вот про отпечатки пальцев не надо)))) Их вообще то по дактилоскопической формуле ищут. В компьютерных системах формула намного сложнее, чем для ручного поиска, но общий принцип остается тот же. Никто не сравнивает две картинки с отпечатками… Не смотрите детективы… они редко показывают, что и как действительно работает. Вы же не верите, что сравнительный анализ ДНК делается в оптическом микроскопе, как это показано в сериале «След» например?
Да детективы я не смотрю. Ищут отпечатки то все равно в бд потипу оракла и никуда от хешей они не уходят. Просто другие запросы и организация хранения в силу особенностей типа данных. 2 сек на сто лямовые бд это запросы текущего рынка. Типа США и Индии. Ну канеш перегнул чутка) Как раз недавно проводился конкурс и наши там показали прекрасные результаты.
habrahabr.ru/post/250725
Как показала практика md5-хеши по файлам изображений достаточно часто дают ложные коллизии. Приблизительно на 1.5 млн картинок было около 20 тысяч случаев.
Что странно… там вроде бы вероятность коллизии два в двестипятдесятшестой степени…
Да, это тоже меня удивило, но факт остался фактом. Разгребал последствия этого, когда пришёл работать в один крупный интернет-магазин.
а можете привести 2 осмысленные фотографии которые дали коллизии?
Сейчас я там уже не работаю, но из специфики можно было выделить только то, что преимущественно проблемы возникали с превью-картинками. Размер порядка 100х100px, формат JPEG.
да, такое можно сделать специально, но получить даже 1 случай коллизии мд5 на обычных 1 500 000 файлов с разным контентом нереально
1.3% коллизий, это даже для crc32 на такой выборке дофига (1.5кк / 2 ^ 32 = 0.03%)
а 1.5кк значений это 4 * 10 ^-33 от всех возможных md5, что как бы намекает
Я не очень понял в каком случае стоит рассматривать облачные решения для хранения фоток? Бонус только в том, что место дешевле? При каких обьемах это становится существенным?
Просто головной боли сразу сильно больше с оплатой отдельной и прочим.
Облачные решения для «обычного использования» весьма дороги получаются.
Мы в результате поигравшись в облака (где каждый раз считаешь сколько обойдется закачать/скачать данные или не дай бог посещаемость повалит внезапная от конкурентов), пришли к выводу, что дешевый сервер в германии за 40 евро с 4 ТБ места и 30Тб траффика на 200мбитном порте во-первых обойдется конкретно дешевле, а во-вторых спать будешь спокойнее… да и сам сайт на нем же можно захостить.
в принципе, да. Пока стоимость привлечения клиентов на востоке за Москвой не станет слишком высокой с серверами в Германии. Тогда нужен будет уже CDN по России
А что с самой простой отказоустойчивостью?
Отказоустойчивостью в каком именно плане?
С железом/софтом? У облаков не так уж редко случаются проблемы, у амазона тоже эпик фэил был, у многих более мелких облаков данные несколько раз пропадали.
Отказоустойчивость к ддос атакам? На облачном провайдере при этом влетаешь на такие деньги за ресурсы, что думаешь «ну его на фиг лучше бы упало».
В случае своего сервера у тебя по крайней мере есть доступ к твоей железке через kvm, а не пассивно ждешь пока «что-то кто-то откуда-то восстановит».
С нашей точки зрения по отказоустойчивости для «обычного использования» (опять же), сервер и облако примерно паритетны. Возможные проблемы разные, по разному решаются, но размер проблем в целом сравним.
Ну я конкретно интересовался как решаете проблему выхода из строя вашего сервера. Сервис продолжает работать?
В случае «обычного сайта» считаем вполне достаточным регулярные бакапы вдс-ки (вдс-ки на своем сервере, сайты уже на вдс-ках) на независимый бакап-сервер (чисто файловый или сайто-файловый готовый к работе), откуда сайт может быть развернут в рабочее состояние за время от 15 минут до пары часов (в зависимости от сценария).
substr(md5(microtime()), mt_rand(0, 30), 2)
Как бы это развидеть:)
преобразуйте microtime в строку, и возьмите последние 2 символа, получится тот же эффект.
вообще-то нет, в первом же приближении, microtime это [0-9] а md5 [0-9a-f], то есть для 2х символов в вашем случае будет 100 вариантов, а в исходном коде 256
ну и хеш функция против Н микросекунд это немного разные уровни энтропии
Не придирайтесь, возьмите time заместо и три символа с конца будет вам и шире и равномерно.
$name = md5($photo) . '.jpg';
$dir = substr($name, 0, 2) . '/' . substr($name, 2, 2);

Будет: 02/c4/02c425157ecd32f259548b33402ff6d3.jpg
смысл этих уровней, чтобы файлы распределялись по ним как-можно равномернее, всякие «безымянный.jpg» и т.п. будут портить общую картину
$name = md5(mcrypt_create_iv (16)) . '.jpg';
$dir = substr($name, 0, 2) . '/' . substr($name, 2, 2);

или еще проще и можно длину файла изменять
$name = bin2hex(mcrypt_create_iv (16)) . '.jpg';
$dir = substr($name, 0, 2) . '/' . substr($name, 2, 2);


В вашем случае:
substr(md5(microtime()), mt_rand(0, 30), 2)
MD5 и так дает равномерное распределение символов, совершенно излишне брать его подстроку в случайной позиции.

про случайную в принципе да особого смысла в этом нет, но на «развидеть» явно не тянет
Простите, отвечал вам, но случай, конечно, не ваш, а автора поста. Перепутал.
хотя если вы имели ввиду $photo из статьи, то реализация tmp_name лежит на операционке, да там банально может не быть 4х символов, или у вас может получится несколько больше уровней например 1236, или несколько меньше (вот пример значения tmp_name: /tmp/php/php1h4j1o), в общем вместо контролируемого поведения мы получаем platform specific
ну, а что в этом уж такого плохого?
«критикуя — предлагай!»
Избыточен и сходу непонятен. В нем видится куда более глубокий смысл чем есть.
С учетом того, что «не больше 1000 файлов», mt_rand(1,999); был бы вполне достаточно, плюс было бы сразу понятно что код делает.
Не понимаю, как между собой связан «mt_rand(1,999);» с фразой «не больше 1000 файлов»? Этот ранд никак не ограничит количество файлов в одной папке, а энтропия очень мала, чтобы выйти за рамки «1000 файлов в папке», достаточно всего 998 в квадрате файлов.
Ни слова про то, что надо держать HiDPI/Retina версии.
Не понятно, за что минусы. Человек дело говорит. У статьи название ведь не «о WebP».
У webp мало перспектив относительно увеличения его популярности, разве только при полной доминации blink-браузеров (да и то вряд ли).
Просто по политическим причинам. Mozilla принципиально не хочет webp, не обращая внимание на огромное количество запросов и уже реализованную функциональность, предложенную в патчах. Apple получает выгоду от многих закрытых патентов.

Когда сам разбирался в этой теме, было очень грустно, что формат не хотят поддерживать.
А что мозилла проигрывает от того, что в фф будет webp? Или что выигрывает от его отсутствия?
Не согласен. Давно его уже использую и, почти так, как описано в статье, за счётом небольших нюансов.
На счёт поддержки, на хромиуме уже достаточно много браузеров и он занимает большую долю браузерного рынка. Даже экономя трафик на них — уже есть выигрыш, как минимум для самих пользователей, которые платят за трафик.
К слову, Опера-турбо, именно так и оптимизирует изображения, пережимая все в вебп.
Аналогично, на 60%+ юзеров можно нехило экономить трафика. Давно уже используем в проде.
Я к тому, что дальше хромиума и его производных WebP не пойдет с высокой вероятностью.
Использовать формат имеет смысл даже при 30% поддержке у пользователей, слишком уж он вкусный.
С вами я полностью согласен :)
Когда-то Mozilla и h.264 наотрез отказывались поддерживать.

Привет из 2022.

WebP весьма популярен и поддерживается всеми нормальными браузерами.

Правда, не факт, что он качественен. Я проводил исследование webp в 2013 году, качество webp плохое.

Нужно будет сейчас провести такое же, посмотреть, что изменилось.

Храните терабайты и не парьтесь.
Только не забывайте оплачивать счета.
Облако полезно, когда неизвестно, насколько выстрелит.
Потом выгоднее переводить на железный сервер.
Можно перейти с s3 на что-то похожее, например на swift, минимальными правками кода.
Если трафик большой, S3 будет отдавать довольно медленно, так что практически обязательно придется подключать CDN
CDN + S3 того же Амазона выходит дешевле и практичней, чем просто S3
aws.amazon.com/ru/s3/pricing
До 10 ТБ / месяц $0.090 за ГБ
GET и все остальные запросы $0.004 за 10 000 запросов

aws.amazon.com/ru/cloudfront/pricing
Первые 10 ТБ / месяц 0,085 USD
Запросы HTTP 0,0075 USD

Это если брать в расчет обмен трафиком только по Европе и Штатам.
Уменьшить размер до приемлемого. Нет смысла хранить и показывать оригинал фотографии размером 4000х3000 на сервере.

Если делать полноценную галерею, то следует оставить и оригиналы. Чтобы пользователь мог скачать не только адаптированный вариант, но и оригинал.

convert input.jpg -strip -resize 1000x1000 -quality 90 output.jpg

Это ужас! Eсть masondry, значит время плиток прошло.
В этом случае convert input.jpg -resize 1000x -quality 90 -auto-orient -gravity center output.jpg
  • 1000 по длине, ширина авто
  • -auto-orient — разворот картинки на основе EXIF данных
  • -gravity center — все манипуляции относительно центра


Так же пример для превью:
если исходник 800х600 к примеру, то после
convert input.jpg -resize "400x225^" -quality 90 -gravity center -crop 400x225+0+0 +repage output.jpg

получаем 400х225, притом, что 800х600 будет уменьшена до 400х300 и затем по центру вписана в кадр 400х225 (то бишь обрежет сверху и снизу, но оставит правильную геометрию).
Вот ещё полезные на мой взгляд параметры:

  • -background white
    белый фон вместо прозрачного слоя, который превращается в черный в jpg
  • -flatten
    склеить слои, например у psd или tiff
  • -compress none
    выключить компрессию в некоторых форматах, например miff
  • +profile \"*\"
    убрать лишнюю информацию (но в случае с -thumbnail оно делается автоматически)
  • -interlace ...
    включить или отключить постепенный показ изображения по мере загрузки
  • -unsharp
    правильные настройки сделают изображение получше

В случае большого количества манипуляций и разных размеров, разумно будет подготовить промежуточный размер.
Можно еще определять цветовой профиль изображения и, например, CMYK преобразовывать в sRGB.
Ну и что что есть Masondry. Он тормозит неимоверно.) Вот прям при загрузке подвисает.
В смысле он тормозит? Вы пишите без конкретики.
А конкретика: masondry ждет подгрузки всех изображений, которые с ним обвязаны в галерее, и только после этого показывает картинки.
У меня на нем пара самописных галерей с дизайном из демок, которые есть в гугле. Так если вы правильно ужали превьюшки и сервер у вас не находится в китае (а вы в европе), то на галереях в 50 картинок ни у кого проблем нету. Что до мобильных устройств — старый айпад работает без проблем на 357 картинках (15Мб).
Наконец, бесшовная догрузка реализуется на ajax, ну или по старинке кнопочки по страницам и никто не отменял использовать альтернативу.
по поводу структуры хранения: ab/cd/ef/90/blah-blah.jpg это хорошо, но генерировать такие папки, особенно глубокой вложенности рандомом идея — так себе: вы будете сжирать  inod'ы и важно, чтобы ваш алгоритм создания папок был действительно равномерно распределен, иначе в одних папках будет «пусто», а вдругих — «густо». Для многих проектов имеет смысл создавать на верхнем уровне папку вида yyyy-mm-dd, чтобы сразу было понятно где «древние» картинки, а где — нет. Так проще организовывать инкрементальный бекапы.

Если у вас не просто файла-помойка, то следует все-таки загружать картинки в разные папки, скажем avatars, products и т.д., иначе сложно потом найти концы.

Миниатюры лучше создавать по требованию и кешировать в файловой системе. Практика показывает, что новые размеры могут потребоваться довольно часто — поменялся дизайн, сетка стала другой, упс...., нужны новые размеры и теперь надо 2 недели создавать новые сайзы. По требованию же поменял один хелпер, «прогрел» сайт и переключил на новый дизайн. Можно создать новые миниатюры только на «свежие» картинки, а старенькие пусть создаются только по требованию для тех, кто листает на 134ую страницу каталога.
А мне не совсем ясно, для чего нужна такая структура папок, какая задача решается?
Неужли доступ к файлу по заранее известному имени (+путь) как-то зависит от количества файлов в директории? Для каких ФС такое характерно? Хотелось бы ликвидировать свою безграмотность в этом вопросе.
Ну если совсем в двух словах…
Если рассматривать очень упрощенно, то весь жесткий диск сервера разбит на небольшие разделы, которые пронумерованы. Каждый файл занимает некоторое количество этих небольших разделов. И чем больше файл, тем больше разделов он занимает.

Контроллер жесткого диска превращает понятную нам запись адреса файла ”/usr/var/www/file.bin” в понятную диску команду вернуть файл начинающийся с позиции 12345 и заканчивающийся в позиции 34567.

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

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

Ну полное имя не скажет контроллеру жесткого диска, в каком секторе лежит первый байт файла…
Полное имя файла каким-то образом драйвером фс преобразуется в начальный и конечный байт блочного устройства. Разве не файловая система хранит информацию о «блоках»? Да, эта инфа тоже где-то записывается на блочное устройство, в каких-то там интервалах байт. И эта информация хорошо кешируется. А уж как блочное устройство будет доставать файл — это уже могут быть разные реализации.
Для кого то и секунды на доступ к файлу достаточно, а кто то строит многоуровневое дерево, что бы 0.1 милисекунды добиться… все относительно…
И понятия «много файлов», «большая нагрузка» у каждого свои…
Если Вы с такой проблемой не сталкивались, то это не значит, что все всегда — «ОК».
Подбор показателя сжатия может уменьшить размер исходного файла в несколько раз без заметного ухудшения качества. Логика такая: чем ниже качество — тем легче файл. Обычно используют показатель качества от 80 до 90.

Такие jpeg-файлы, сжатые gd с параметром 80...90 не нравятся сервису google page speed insights.
Ты им хоть 90, хоть 80 поставь — всё равно сервис будет говорить, что можно ещё уменьшить картинку без потери качества. И даже на 70ти, когда уже появляются различимые глазом артефакты — всё равно будет считать изображения неоптимальными и снимать баллы.
При этом изображения, которые предлагает гугл (там есть линк «скачать оптмизированные изображения») действительно и хорошо оптимизированы и потеря качеством человека незаметна. Как они это делают автоматически — не знаю, но либо я что-то делаю не так, либо gd'шная библиотека мало подходит для оптимизации (и как тогда автоматизировать их — непонятно).

PS Кому интересно — эксперимент проводился чем-то вроде такого:
<?php

$tmp_name = $_SERVER["DOCUMENT_ROOT"].'/test1/img001.jpg';
$new_name = $_SERVER["DOCUMENT_ROOT"].'/test1/img001x90.jpg';
$params = getimagesize($tmp_name);
$new_width = $params['0'];
$new_height = $params['1'];

$old_img = imagecreatefromjpeg($tmp_name);
$new_img = imagecreatetruecolor($new_width, $new_height) ;
imagecopyresampled ($new_img, $old_img, 0, 0, 0, 0, $new_width, $new_height, $params['0'], $params['1']) ;

imagejpeg($new_img, $new_name, 90);

?>

т.е. просто пересохранялась картинка без изменения размеров (можно и imagecopyresampled выкинуть — при этом файлы точно такие же получаются).
Всякие сайты по оптимизации картинок знаю.

Если у кого есть рабочий вариант, как нужно правильно оптимизировать под page speed insights — поделитесь. Совет же «сжать gd до 80..90» я воспринимаю как неправильный ответ.
Дело в том, что в файле картинки кроме собственно самой картинки еще содержится куча всякой мета-информации и порой она занимает до 20-30% размера всего файла. GD с этим никак не работает, насколько мне известно. Необходимо картинку дополнительно обрабатывать специальными утилитами типа JpegTran.
+ надстройкой над jpegtran — jpegrescan. Тогда GSI ничего не говорит
После этого можно показывать фотку прямо с Амазона

Вредные советы на Хабре. Если вы отдаёте что-либо из S3, вы платите за исходящий трафик (около $9 за 100Гб), и не можете ограничить отдачу — если я захочу двадцать миллионов раз скачать картинку с котиком на полтора мегабайта из вашей S3 корзины, мне никто не помешает. Всегда ставьте S3 за своим сервером, если хотите исключить риск удивиться счёту за услуги в начале нового месяца.
А еще лучше сценарий, когда картинки отдает CDN, например Cloudflare.
UFO just landed and posted this here
Не помню с какой версии, но через convert тоже можно уже создавать webp. Раньше ставил гугловское приложение для этих целей, сейчас просто использую уже установленный ИмеджМеджик.
Хочу посоветовать использовать еще ImageOptim для оптимизации картинок и фоток. Он применяет кучи известных алгоритмов для сжатия. Единственное будьте острожны с png оптимизаторами, некоторые из них занимают 20+ сек на картинку.
Это позволит избежать ситуации с тысячами файлов в одной папке (это тормозит работу файловой системы и вашу собственную).

А на каком основании делается вывод, что наличие тысяч файлов в одной папке тормозит работу фс?
По этому поводу есть немаловажный нюанс: в ext3, например, есть ограничение в 32К вложенных папок, а вот на количество файлов нет.
Вспомните пожалуйста, что такое каталог с точки зрения файловой системы…
Полагаю, что каталог для ФС — это файл, который грубо говоря содержит в себе список файлов, «принадлежащих» ему. И с этой точки зрения в зависимости от ФС более длинный путь как раз будет медленнее, т.к. может просматриваться цепочка каталогов для определения уникального имени файла.
Просветите, пожалуйста, если я ошибаюсь.
В общем Вы правы, но есть некоторые нюансы. В файловой системе под хранение информации о каталоге (список файлов) отводится определенное место. За точность цифр уже поручится не могу (давно этим занимался) но в NTFS это три сектора диска. то есть 16 килобайт.
Если мы кидаем больше файлов, чем влезает в эти 16 килобайт то головке винчестера приходится делать лишние движения по диску (на SSD просто поиск в большем списке, что не критично а вот на HDD критично очень.) для того, что бы собрать весь список, при этом пока весь список не будет прочитан с диска, местоположение файла который ищется на диске не будет получено, даже если он в списке первый.
Вот и получается, что первые три блока считываются за один проход головки ибо лежат в одном месте. А потом головка начинает дергатся в поисках продолжения. В общем, чем больше файлов в каталоге, тем больше движений головки диска… А по времени, поиск в двух вложенных каталогах занимает столько же времени как и поиск в одном каталоге где не 1000 а 1001 файл (цифры условные)
Как то так…
В каждом конкретном случае, да может быть закинуть в каталог больше файлов может быть выгоднее чем плодить поддиректории, но если мы не знаем сколько файлов может быть в каталоге, то выгоднее всетаки углубить путь но не выходить за какое то разумное количество. в 1000-1500 файлов в одном каталоге.
каталог это по сути спискок inode вложенных файлов/каталогово и то чтобы обратиться к файлу по имени нужно их тупо перебрать, так вот вместо поиска по списку из миллиона элементов, можно искать в 256, что как бы быстрее, сравните:
поиск в списке 1 000 000 элементов, разбиваем это на aa/aa (равномерно 16 файлов в каталоге), нужно перебрать 256 + 256 + 16 = 528 элементов
также вы дружно забываете про кеш файловой системы в ram.
под линукс есть dir_index он выполняет индексацию inode через хеш таблицу по имени, что несколько убирает острую необходимость такой структуры
каталог это по сути спискок inode вложенных файлов/каталогово и то чтобы обратиться к файлу по имени нужно их тупо перебрать, так вот вместо поиска по списку из миллиона элементов, можно искать в 256, что как бы быстрее, сравните:
поиск в списке 1 000 000 элементов, разбиваем это на aa/aa (равномерно 16 файлов в каталоге), нужно перебрать 256 + 256 + 16 = 528 элементов

Спасибо! Вы намного короче описали то, что я расписал выше!
В моей практике встречалась ситуация когда 6 терабайт в основном картинок (примерно по 1.5 мегабайта в среднем) было уложено в 4 каталога. В этом случае со всеми кешами и оптимизациями доступ к одному файлу все равно был около 5 секунд!!! На zfs если мне память не отшибло…
UFO just landed and posted this here
Не совсем очевидно, почему оптимальная длинна имени папки — 2 символа?
Также интересно, какая оптимальная вложенность?
UFO just landed and posted this here

После этого можно показывать фотку прямо с Амазона:

https://s3-eu-west-1.amazonaws.com/букет/photo_name.jpg

а есть возможность эту фотку ресайзить как-то по простому? например добавить ?width=400 в конце. или как это делается?

Sign up to leave a comment.