bash.im ithappens.me zadolba.li

Программизмы

13487

Когда запятые кончились

Корректность значения не проверяется, говорите? Их есть у меня!

Год где-то 2005, в районных электросетях (РЭС) работает биллинговая программа. Ну, работает более-менее, вроде всё настроено. Мануалов, как водится, нет, приходится всё делать методом не всегда научного тыка.

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

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

13485

Только так - или никак

Знакомая работает в медицинском учреждении. Получили новый аппарат для экспресс-анализа на наркотики. Сам аппарат — коробочка 5×7 см, по usb подключается к ноутбуку. В коробочку вставляется картридж с анализом, она его сканирует. На ноутбуке программа, сравнивающая цвета полосок на скане с эталоном и считающая концентрации.

Все нормально, но при попытке записи результата выдаётся ошибка: «7:» is not valid integer data.

Пляски с бубном дали результат парадоксальный — все заработало при установке в системе формата времени HH: MM: SS.

Теперь я не могу понять, откуда растут руки у разработчиков? Взять системное время в текстовом виде, порезать по два символа в три целочисленных поля и даже не сделать проверки на корректность значения…

13484

Древние грабли

Древнее золото, говоришь?

А у меня сразу возник вопрос. Если обработка XML требовала затянуть в память все, и там разбирать ("проблема была в сильной связанности") - то почему загрузка в CSV этого же не требовала?

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

Я вот совсем недавно исправлял проблему - нельзя было загружать XML'и больше определенного размера. Памяти не хватало. Оказалось, там парсер грузит всю структуру в память целиком и только потом обрабатывает. Заменил на потоковый. Потребление памяти константное, скорость работы возросла.

А обмен через файлы - это большая коллекция граблей с автоподзаводом. Возможно, уже пришла пора открыть для себя что-нибудь более новое?

13481

Древнее золото редко блестит

Однажды я писал утилиту для анализа большого объёма сильно связанных данных на XML + C# — заказчик хотел модные (в 2007 году) технологии. Ничего сложного — XML-документ загружался в память, последовательно обрабатывался, результаты складывались в базу. Проблема была в сильной связанности — при обработке почти каждого узла приходилось подгружать целые секции из разных концов этого же документа.

Когда соотношение объёма входных данных и объёма ОЗУ машины пересекло критическую отметку, программа сошла с ума. Показатель Time in GC достиг значения 98%, а значит, программа не работала, вместо этого среда выполнения занималась очисткой и дефрагментацией памяти. Проведённое расследование показало — при нехватки памяти и попытке подгрузить дополнительные данные для обработки текущего узла ОС скидывала обрабатываемые данные в своп, а затем доставала их обратно. И сборщик мусора работал над свопом, что в тысячи раз медленнее работы с ОЗУ.

Решением был файловый ввод-вывод. Я переписал программу, используя свой велосипедный страничный ввод-вывод и формат CSV вместо громоздкого XML. После этого она могла обрабатывать любой объём данных, независимо от ограничений ОЗУ машины, с постоянной скоростью, не отвлекаясь на дефрагментацию своп-файла и вообще его не используя.

К чему я всё это. Файловый обмен — замечательная вещь, и мало форматов лучше, чем CSV. Он легко читается машиной и человеком, его поддерживают большинство программ — от офисных до научных пакетов. Используя магию bash, его можно бить на части (подзадачи для вычислительной фермы, например) или объединять (результаты вычислений), записывать в сеть, в устройства, в другие процессы, выложить в облачное хранилище или отправить по email, перезапросить в случае отказа сети, создать резервную копию, принять и обработать тысячей и одним способом.

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

13434

Совпадение? Не думаю!

Вступлюсь за честь коллег из геймдева.

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

Во-вторых, сессия для инициализации рандома используется в одиночных играх с целью борьбы с читерской магией load-save. Другого смысла постоянно дёргать seed просто нет.

В-третьих, игрокам вообще много что кажется, и они с радостью это интерпретируют как факты. Плюс — confirmation bias. Я помню случай, когда игроки были свято убеждены, что по случайному номеру в ссылке для предотвращения кеширования можно было определить успех ремонта предмета. И никого не смущало, что к скрипту шли десятки обращений в секунду и от момента генерации ссылки до последующего запроса рандом дёргался более тысячи раз.

Это же касается вообще любых якобы повторяющихся паттернов в рандоме. И «вычисления алгоритма работы». Чего его вычислять — всё есть в открытом доступе, почти всегда используется штатная функция выбранного языка разработки. Только никому это знание ничего не даёт.

Искренне порадовался аргументу про сокращение выборки. Ясное дело, что чем меньше выборка, тем более она неравномерна — это очевидно. Нетрудно получить «решку» в 8−10 случаях из 10, шанс на это чуть более 5%. А вот получить её в 80−100 случаях из 100 уже вряд ли удастся хотя бы раз за миллион попыток.

P.S. Ну, а парень из предыдущей истории просто не учёл, что по умолчанию большинство генераторов псевдослучайных чисел инициализируются от текущего времени с точностью до секунды. Так что, запустив одну и ту же программу на разных машинах, вторая из которых отстаёт примерно на пару секунд, можно получить полностью идентичные результаты.