31 авг. 2009 г.

Растеризация Делоне


Автоматический поиск дубликатов в коде

Инструменты для автоматического поиска одинаковых участков кода:
  • Simian (платный, работает с любым кодом)
  • Duplo (GPL, C/C++/Java)
Интересная статья по теме:

30 авг. 2009 г.

ThinkTank: Digital Holster

ThinkTank: Digital Holster 30. По виду — приличная фотосумка, вмещающая 5D MKII с одетым объективом 70-200. У Мартина Фаулератакая же.

Нужно будет попробовать.

Wordle: облако слов из блога

Wordle: Craters of the Mind

Lua Alchemy во В Контакте

Энтузиасты доработали демо Lua Alchemy, и встроили его во В Контакте:

SSD vs. Linux

Интересная цитата на тему рискованности использования SSD-дисков (особенно под Линухом):
<...>The bug is an assumption in most standard Linux filesystems (including ext2 and ext3). They all assume that the update granularity of the underlying block device they're writing to is greater than or equal to the filesystem's granularity. (I.E. that the smallest write you can do to the block device is the same size or smaller than a filesystem block.) Oh, and also that the alignment works out, so that data you're not writing doesn't get destroyed as "collateral damage" by a failed write operation.

This isn't true for flash, which has "erase blocks" up to a couple megabytes each. As with burnable cd-roms, you have to do an "erase" pass on an area of flash memory before it can have new data written to it. You can't erase just part of an erase block, it's all or nothing.

Actual Linux flash filesystems (like jffs2) are aware of this. That's why you can't mount them on an arbitrary block device, you have to feed them actual raw flash memory hardware (or something that emulates it) so they can query extra information (erase block boundaries). They cycle through the erase blocks and keep one blank at all times, copying the old data to the blank one before making the old one the new blank one. (That's why mounting them is so slow, the filesystem has to read all the flash erase blocks to figure out which one's newest, and which order to put them in.)

But flash USB keys pretend to be normal USB hard drives, which you format FAT, or ext3 or some such. And when you write to them, what they're actually doing internally is reading a megabyte or so of data into internal memory, erasing that block of data, and then re-writing it with your modifications. Generally they'll cache some writes first so they're not rewriting a whole megabyte of flash every time you send another 512 byte sector (which would not only be insanely slow but would run through the limited number of flash write cycles pretty quickly).

This sounds fine... until you unplug one during a write and the device loses power between the internal "erase" and "rewrite". Suddenly, the sector you were writing to might be ground zero in the middle of a megabyte of zeroes. You can lose data before, after, or on both sides of the sector it was updating.

Journaling doesn't pretect you from this, because it was built on the assumption that data you weren't writing to didn't change. The "collateral damage" effect of flash erase blocks undermines what journaling is trying to do, by violating the design assumptions of conventional Linux filesystems. In fact if the journal isn't what got zeroed, the journal replay may complete happily and mount the filesystem and hide the fact anything went wrong... until you try to use the missing data, anyway. (Not that using a non-journaled filesystem would actually improve matters, but it's less likely to give you a false sense of security.)

For further reading, see Linux filesystems expert Valerie Aurora's excellent post on why she personally doesn't want a flash disk in her laptop.

Rob Landley.

22 авг. 2009 г.

Design patterns or best practices for shell scripts

Полезное обсуждение на StackOverflow.com: Design patterns or best practices for shell scripts.

Рассказывается о:
  • Command line options
  • Function calls
  • Error prone situations
  • Python-like modularization
  • OOP
  • Trapping and handling signals
И, самое главное:
If you have to use the kind of things I wrote here, it means that your problem is too complex to be solved with shell. Use another language.
Ещё ссылки:

Lua-Noise

Никто не захотел поделиться модулем для генерации шума Перлина для Lua. Пришлось сделать свой:


Осторожно: сырой код!

21 авг. 2009 г.

Альтернатива блоксхемам во Flow Based Programming

Worley Noise

Интересный "антоним" к шуму Перлина (Perlin noise) — шум Ворли (Worley noise) или клеточный шум (cell noise).

Шум Перлина характеризуется мягкими переходами:

(Не нашёл картинку на flickr'е о_О)

Переходы в Шуме Ворли же наоборот — резкие:


Интересно, что шум Ворли тесно связан с диаграммами Вороного (Voronoi diagram).

Интересные примеры (в частности) скрещивания шума Перлина с шумом Ворли можно посмотреть здесь. (Ещё интересная ссылка.)

Ссылки:

20 авг. 2009 г.

К вопросу о Lua

Who should use Lua?

<...>

Luiz: The problem is that most designers do not see this need until much later, when much code has already been written in say C or C++, and they feel that it's too late now. Application designers should consider scripting from the start. This will give them much more flexibility. It will also give them better perspective about performance, by forcing them to think where the application needs raw performance and where it does not matter at all, and so can be delegated to the easier, shorter development cycle of scripting.

— Luiz Henrique de Figueiredo,
interview for Masterminds of Programming

Цитата

И к чему всё это? Лучше бы водки выпили...
Из писем Белинского Гоголю.

Eats, shoots and leaves

Друг написал в своём блоге (пунктуация сохранена):




...На нас не капает правда...




Всего одной запятой не хватает, а какой глубокий философский эффект!

14 авг. 2009 г.

iPhone 3GS vs. VFP

В новом iPhone (как и в новых ARM-ах вообще), как оказалось, серьёзно урезан векторный сопроцессор.

Жаль.

Cсылки:

1. http://diaryofagraphicsprogrammer.blogspot.com/2008/11/iphone-arm-vfp-code.html#c7064614874794429950
2. http://lua-users.org/lists/lua-l/2009-08/msg00174.html
3. http://lua-users.org/lists/lua-l/2009-08/msg00338.html

XZ

Следующее поколение LZMA: архиватор XZ.

select() loop for X events

Оказывается, события X Window можно читать из select'а:


dis = XOpenDisplay(DISPLAY);
fd = ConnectionNumber(dis);

FD_SET(fd, &in_fds);

select(fd+1, &in_fds, NULL, NULL, NULL);

...

Automated Unit-Testing on iPhone

Несколько полезных ссылок:

Создание *.ipa для ad-hoc дистрибуции

При сборке проекта в Xcode получается папка *.app — бандл приложения.

Тестерам значительно удобнее отдавать вместо папки, один файл — *.ipa. В отличие от *.app, он устанавливаетсч в iTunes автоматически по двойному щелчку.

Приятная мелочь — в *.ipa-файле задать картинку для отображения приложения в iTunes — так, чтобы всё было совсем уж по-взрослому.

Две вещи, на которые нужно обратить внимание:

1. Тестерам вместе с *.ipa нужно отдавать *.mobileprovision, который был сгенерирован при привязке UDID-а их iPhone к аккаунту разработчика.
2. В каждом новом билде обязательно нужно увеличивать номер версии — иначе iTunes не обновит установленное приложение.

Вот скрипт для генерации *.ipa. Удобно добавить его в проект Xcode последним шагом сборки. Скрипт заточен под мои конкретные нужды, но всё должно быть понятно без комментариев.

#!/bin/bash

VER=$1

if [ "${VER}" != "lite" -a "${VER}" != "full" ]; then
echo "bad version ${VER}, exepected 'lite' or 'full'"
exit 1
fi

RES=./res
COMMON=${RES}/common
CONCRETE=${RES}/${VER}

APP=${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.app
PAYLOAD=${TEMP_FILES_DIR}/Payload
IPA=${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.ipa

if [ ! -d "${APP}" ]; then
echo "output .app not found: '${APP}'"
exit 1
fi

if [ "${PLATFORM_NAME}" = "iphonesimulator" ]; then
echo "Simulator detected. Skipping .ipa generation"
exit 0
fi

rm -rf ${PAYLOAD}
mkdir -p ${PAYLOAD}/Payload
cp -Rp ${APP} ${PAYLOAD}/Payload
cp ${CONCRETE}/standard/iTunesArtwork.png ${PAYLOAD}/iTunesArtwork
ditto -c -k ${PAYLOAD} ${IPA}
rm -rf ${PAYLOAD}


Пока раскапывал этот вопрос, открыл для себя команду ditto. Если сборка идёт не под OS X, ditto можно заменить на zip — *.ipa-файл — это просто zip-архив.

Причины отказа приёмки в AppStore

Несколько полезных ссылок:



Также в тему:

LibraryThing

Каталог информации по книгам и авторам: LibraryThing.com. Например, страница про Ларри Нивена.

Linux command line

Несколько ссылок на коллекции полезных трюков командной строки:

* StackOverflow.com: What is your single most favorite command-line trick using Bash?
* commandlinefu.com — сайт, подобный StackOverflow.com, но посвящённый исключительно консольным командам.
* The Definitive Guide to Bash Command Line History
* Моя личная коллекция

Xcode vs. iPhone OS 3.0.1

Текущий iPhone SDK несовместим с самой свежей прошивкой iPhone — 3.0.1.

Для того, чтобы восстановить совместимость, нужно последовать указаниям iPhone OS 3.0.1 Advisory от Apple, и выполнить команду

$ ln -s /Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0\ \(7A341\) \
/Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0.1

12 авг. 2009 г.

Unknown error

Потратил день на отлов

Failed to launch simulated application: Unknown error.

при запуске айфонного приложения в симуляторе.

Путём пошагового воссоздания проекта выяснил, что симулятор сходит с ума, если в бандле есть пользовательская папка "resources".

Нехорошо.

В очередной раз подтвердил действенность правила: если пытаешься что-то воспроизвести путём шаманских манипуляций, записывай каждый шаг отдельным коммитом в Git!

7 авг. 2009 г.

Lua Núcleo: coro.yield_outer

Обновил мастер Lua Núcleo.

Добавил модуль coro для прозрачного проброса yield'а вверх по цепочке корутин.

Корутины нередко используются для передачи управления наружу из Lua. Например, для работы по сети, когда Lua'шный стейт откладывается в пул до получения ответа, а по получении ответа делается resume. В этом случае все сетевые операции в Lua делают yield.

В обычном случае это делает невозможным использование этих сетевых операций внутри пользовательских корутин. Если же пользоваться новым модулем, это ограничение снимается. Для этого нужно:
  1. Для всех пользовательских корутин вызывать coro.resume_inner вместо coroutine.resume.
  2. Во всех сетевых операциях вызывать coro.yield_outer вместо coroutine.yield.
  3. В пользовательском коде использовать coro.pcall вместо pcall-а.
  4. Результат coroutine.resume во внешней корутине перед обработкой пропускать через функцию coro.eat_tag.
Также перетянул работу Георгия: tserialize и tdeepequals; обе функции — с поддержкой рекурсивных таблиц.

Автофотограф для вечеринок от Sony

Sony Party-shot IPT-DS1 фотографирует вечеринки в автоматическом режиме.