Оглядываясь вкруг себя, я размышляю о том, что не так уж часто, мне кажется, люди остаются программистами много-много лет. Чаще всего постепенно переходят в менеджеры, на протяжении нескольких лет, поначалу еще продолжая писать код, но потом все больше и больше начальственные обязанности занимают все время. Часто уходят в Product Management. Некоторые, реже, в маркетинг. Многие уходят в мир стартапов и становятся сами себе бизнесменами - даже если они продолжают писать код, это уже работа на себя. Обратное передвижение, из других профессий в программисты, почти никогда не случается в середине карьеры, только в начале (из математиков, физиков, инженеров, просто кого угодно еще, если есть склонность к этому делу).

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

Мне 37, и если не считать несколько подростковых подработок, я зарабатываю на жизнь программированием чуть более 20 лет. Большую часть этого времени - в компаниях, где я сам себе не хозяин. До сих пор я сознательно противился подводному течению, которое влечет программистов в менеджмент, по двум причинам. Мне кажется, что мне это меньше нравится, и мне кажется, что у меня это не очень хорошо получится. До сих пор я не жалел об этом решении. Но что я буду делать еще через 20 лет, предполагая, что буду жив, относительно здоров, и все еще буду работать? Многое еще может измениться; но если я не буду специально стараться и трепыхаться, закон инерции жизни говорит, что и в 57 лет буду нажимать на клавиши и вводить ключевые слова в текстовом редакторе в какой-то компании. Будут ли хорошие, интересные возможности и проекты для 57-летнего меня в индустрии, какой она станет через 20 лет? Сейчас в нашей индустрии, повторюсь, программисты за 50 есть, но их довольно мало...

Недавняя дискуссия в HN ("What happens to older developers?") подстегнула мои мысли по этому поводу, и, хоть не дала конкретного ответа, предложила много возможных. Верхний комментарий там хорошо подытоживает разные варианты развития, которые я описал в выше: идти в менеджеры, оставаться программистом и углублять свое мастерство, идти в бизнесмены-стартаписты, уходить в совсем другую профессию. Есть в комментариях там немало таких, как я, предпочитающих пока что при всех равных зарабатывать ключевыми словами в редакторе. Те из них, кому за 50, пишут чаще, что коль скоро сохраняют технические знания и идут в ногу со временем, не затрудняются найти работу - хоть это в основном американские мнения, в других странах может быть по-другому. Но неясно, сколько таких осталось из тех, кто хотели того же, но обнаружили, что им трудно поменять место работы в пожилом возрасте, или что им трудно принять тот факт, что все сверстники обошли их по иерархическим лестницам, или что просто надоело.

Конечно, только я сам могу решить для себя, следует мне "специально стараться и трепыхаться", или продолжать с ключевыми словами и редакторами. Но буду рад узнать мнение программистов, нынешних и текущих, переквалифицировавшихся в управдомы или стремящихся к этому, на эту тему.
Уолтер Брайт вспоминает, как он сохранял конфигурацию в своих программах в те давние времена, когда будущие изобретатели XML еще пешком под стол ходили:
Back in the bad old DOS days, instead of creating a file format for saving/loading the configuration of the text editor, I simply wrote out the image in memory of the executable to the executable file. (The configuration was written to static global variables.)
Running the new executable then loaded the new configuration. This worked like a champ, up until the Age of Antivirus Software, which always had much grief over writing to executable files.
It's a trick I learned from the original Fortran version of ADVENT.

Думаю, он имееет в виду COM-файлы, потому что с EXE такое бы не вышло, если мне не изменяет память (из-за релокации). Хотя при желании в EXE-файле можно было бы перезаписать только часть, соответствующую глобальным переменным конфигурации - найти, где это, в файле было легко.
ESR (Эрик Реймонд) написал подробное и ясное объяснение того, как в Си выравниваются структуры (alignment). Тем, кто не сталкивался с этим вопросом и не знает, интересно будет почитать.

Почему он при этом назвал свою статью "The Lost Art of C Structure Packing", мне непонятно. ESR почему-то считает, что в наше время все разучились это делать, или просто новые программисты на Си не знают об этом, а помнят одни "старички". Я не вижу оснований так считать. Как мне это помнится - что 20 лет назад, что сейчас: начинающие или малоопытные программисты на Си/С++ не знают про alignment, а опытные знают и по привычке правильно расставляют поля внутри структуры.

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

Из дискуссии на Hacker News по поводу этой статьи я хочу процитировать одну мысль про процессоры Intel, которая мне понравилась, и как-то не приходила самому в голову:
Intel actually put in an feature to trap on unaligned access starting with the 486 (and it still exists today) - look up the AC "alignment check" flag. Of course almost no one used that feature since x86 supported unaligned access from the very beginning, and I think this flexibility is one of the reasons why it's stayed competitive: lots of features initially, not all of them optimal (e.g. division instruction on the 8088 was extremely slow), then improve on them with each new microarchitecture, the result being that existing software benefits from these improvements. In contrast, an architecture that didn't support unaligned access would not do much for existing software if faster instructions for unaligned access were introduced since they wouldn't be used.

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



Такое было время, сынок.

(можно и сейчас это сделать, кстати; вот полный выпуск журнала с исходниками на страницах 102-106. Там даже есть особые контрольные суммы после каждой строки, чтобы проверить, что правильно набиваешь. Проверяет контрольные суммы отдельная программа, исходники которой тут же приведены в этом же номере. Тоже с контрольными суммами).
1) Языки программирования, которые я хотел бы изучить подробнее и составить свое мнение, если найду для этого время:

хочузнать: Erlang, Clojure, Scala, Rust, OCaml, Julia

2) Языки программирования, которые я не знаю изнутри, лишь немного или совсем не, но как-то не тянет их изучать и вряд ли займусь:

нехочузнать: Ruby, Dart, C#, F#, D, R.

А как у вас выглядят подобные два списка?
x5602 - a simple 6502 CPU emulator

Проект, демонстрирующий очень простой эмулятор микропроцессора 6502 (который широко использовался в самом начале эры персональных компьютеров - Atari, Apple II, Commodore 64...). Если вы знаете язык C даже в общих чертах, и никогда не писали код, симулирующий работу процессора, то этот проект - хорошее введение в то, как к этому вообще подходить.

Я иногда думаю, что должно быть больше обучающего кода - сознательно игрушечных проектов, написанных специально для того, чтобы научить читателя, с чего начинать и как все организовывать в данной области. Таких вот, как этот проект. Наверное, самые обычные примеры этого - разнообразные игрушечные операционные системы и компиляторы, использующиеся в университетских курсах на эти темы.
Кажется, я никогда не записывал здесь подробной истории того, как я писал движок для игры, подобной Wolfenstein 3D. Я читаю сейчас книгу об истории id Software и ее создателей (о книге напишу отдельно), и то и дело вспоминаю эту старую историю. Заодно понял, что многие подробности уже забыл, так что лучше записать, что еще помню.

Игра Wolfenstein 3D появилась весной 92 года. Тем, кто помоложе, придется поверить мне на слово: это была сенсация, потрясшая весь мир компьютерных игр. Очень трудно было поверить, даже глядя прямо на экран, что PC-шки того времени действительно могли так быстро показывать от первого лица движение в трехмерном мире (пусть даже он был лишь условно трехмерным: высота объектов и перспективы не менялась). Ничего подобного никто до этого не видел.



Осенью 93 года я начал учиться на первом курсе факультета компьютерных наук хайфского Техниона. Мне было 17 лет. У меня к тому времени было немало опыта работы с графикой в ассемблере и оптимизации графических алгоритмов и вообще ассемблерного кода. Из языков высшего уровня я все еще предпочитал Турбо Паскаль, хотя уже знал C.

Видимо, в сентябре или октябре - точно вспомнить не могу - параллельно с началом учебы я начал работать над попыткой создания трехмерного движка, равного по возможностям Wolfenstein 3D. Я познакомился через каких-то друзей с владельцами компьютерного магазина в Хайфе, у которых простаивал без использования компьютер с новым и быстрым процессором со странным названием "Пентиум". Он был заметно быстрее моего домашнего компьютера с 486DX-2, к которому у меня в любом случае был доступ только на выходных, он остался дома в Ришон ле-Ционе. Мне хотелось посмотреть, на что способен Пентиум; я договорился с хозяевами магазина, что буду сидеть за ним в свободное время и писать свой движок, а если он когда-то превратится в настоящую игру, то они ее смогут продавать или что-то в этом роде. Не помню подробностей соглашения, которое в любом случае было устным и неформальным. По правде сказать, я не думал о своей работе, как о создании движка, и у меня не было серьезных намерений написать свою игру. Например, я совершенно не умел рисовать текстуры или объекты, и не знал, где найти человека, который умеет, и не собирался его искать. Я хотел воссоздать магию Вульфенштейна - магию свободного хождения по трехмерному лабиринту, с разрисованными стенками и объектами вроде врагов или полезных предметов на земле. Я не понимал, как им удалось это сделать, и надеялся, что хотя бы на быстром Пентиуме я смогу повторить это достижение.

Я нашел небольшую статью на какой-то BBS, которая объясняла основные принципы ray-casting'а, и там был пример простого алгоритма, который вычисляет, какие стенки видит игрок, с помощью рей-кастинга. Алгоритм, кажется, был на C. Я разобрался с его смыслом, переписал его на Паскале, и добавил репрезентацию уровня и простое движение курсорными клавишами. После долгой отладки это заработало, но каждый фрейм рисовался несколько минут, можно было видеть на экране, как код медленно меняет одну вертикальную линию за другой.

Рей-кастинг работает по тому же принципу, по которому, как когда-то считалось, работает зрение. Древние греки думали, что из глаз выходят специальные лучи, долетают до предметов, отражаются от них и возвращаются обратно, и так мы видим (точнее, не все древние греки так думали, была и другая теория, согласно которой предметы излучают свои миниатюрные копии, и они доходят до глаз). При рей-кастинге программа следит за тем, где находится игрок на карте уровня, и куда смотрит, какое у него поле обзора. Это поле делится на 320 (например) вертикальных линий, и мы как бы запускаем из точки, в которой находится игрок, 320 гипотетических лучей по всем 320 направлениям, и смотрим, до какого объекта на карте долетает каждый луч. Если какой-то луч долетает, например, до стенки, то мы знаем, какая эта стенка, какая на ней должна быть нарисована текстура (картинка), и какая именно вертикальная линия из этой текстуры должна стоять в этом месте. И самое главное, зная расстояние, которое прошел луч, мы вычисляем, какой должен быть размер
этой линии на экране. Мы берем нужную линию из текстуры фиксированного размера (например, 64x64 пикселя), и увеличиваем ее или уменьшаем до нужного размера: если стенка далеко от игрока, ее линия может занимать 6 пикселей на экране, а если близко, то 100.

Это и есть основной принцип. Когда к стенкам добавляют объекты, возникают дополнительные сложности, потому что объект, например, враг, не занимает целиком квадрат на карте, как стенка. Он частично прозрачен: в зависимости от того, где в его квадрат попадает луч от игрока, нужно или рисовать его, или вести луч дальше. Или можно в любом случае довести луч до дальней стенки, в процессе собирая информацию об объектах на дороге, и отрисовать их поверх стенки. Можно по-разному к этому подходить. Но у меня еще и до объектов, с одними голыми стенками, все рисовалось очень медленно.

Я переписал основную функцию рендеринга на ассемблере, и это заработало намного быстрее, но все еще невыносимо медленно: на Пентиуме перерисовка экрана занимала несколько секунд. Я оптимизировал код на ассемблере, как мог, используя всякие хитрые трюки, но это все равно было намного, намного медленнее на Пентиуме, чем Wolfenstein 3D вообще даже на 386-м.

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

Наконец в один из выходных я запустил Wolfenstein 3D на своем домашнем компьютере под отладчиком SoftICE (очень хороший был отладчик в эпоху DOS и раннего Windows). Мне хотелось попробовать понять, как же все-таки они делают перерисовку экрана, и на каком языке написан движок. После нескольких часов блужданий по машинному коду я нашел куски, которые выглядели как копирование данных текстуры на экран, с одновременным увеличиванием/уменьшением. Это были короткие куски кода, явно написанные на ассемблере (они использовали регистры не по стандартным конвенциям C или Паскаля). Я решил, что движок Вульфенштейна написан на чистом ассемблере, что меня не очень удивило. Но когда я попытался разобраться, как они оптимизировали копирование, чтобы оно было быстрым, меня удивило отсутствие условных прыжков. Похоже было на то, что одна такая функция копировала 64-пикселевую линию, например, ровно в 40 пикселей на экране, не больше и не меньше, а другая копировала в 42, и так далее. Поэтому каждой функции не надо было собственно подсчитывать, куда ставить какой пиксель из текстуры, каждая из них заранее знала свою работу, не проверяла ничего, не держала никаких счетчиков, а просто раскидывала пиксели туда-сюда. Но это ж адская была бы работа, подумал я, писать вручную на ассемблере отдельную функцию копирования текстуры для каждой возможной высоты на экране. И тут до меня дошло, что движок Вульфенштейна генерирует эти функции на машинном коде прямо во время работы программы.

Я позаимствовал эту идею оптимизации, но не сам код из Вульфенштайна - мне хотелось сделать это самому. Через несколько дней напряженной работы (в основном отладки, потому что ошибки в сгенерированном машинном коде часто означали, что нужно перезагрузить компьютер) у меня был готов код на Паскале, который в начале работы программы генерировал функции для копирования текстур во все возможные размеры. Во время отрисовки экрана эти функции вызывались через таблицу ссылок, проиндексированную размером линии на экране. Когда я запустил все это, скорость работы кода меня ошеломила. На Пентиуме движок работал так быстро, что мне пришлось добавить замедление движения - иначе при нажатой клавише движения вперед игрок летел с ненатуральной скоростью. На 486-м дома, и даже на 386-м процессоре, движение в текстурном лабиринте работало так же быстро и гладко, как в самом Вульфенштейне.

Затем я добавил ограничение движения - чтобы игрок не мог проходить сквозь стены (это легко), и поддержку объектов (вот это было тяжело, возился еще несколько недель, пока не заработало достаточно быстро). Сделал отдельный файл-демку, который позволял игроку бегать по простому лабиринту, и показал нескольким друзьям и знакомым. И... забросил все это.

А через несколько недель, в декабре 93-го согласно Википедии, появился Doom, в котором была (ограниченная, но все равно круто) поддержка высоты, а также освещение, меняющееся с размером. id Software не сидели на месте полтора года со времени выпуска Вульфенштейна, и опять поразили весь мир, добившись на первый взгляд невозможного. Я поразмышлял немного о том, как мой движок улучшать в эту сторону, но работать над этим не стал. Более интересно было проводить время в университете, знакомиться с другими студентами и студентками, а также общаться по IRC с людьми со всего мира.
Мартин Одерски, создатель языка программирования Скала, так отреагировал на блог-запись с критикой Скалы:
Seems hardly a weekend goes by these days without another Scala rant that makes the Hacker news frontpage. [...]

There certainly seems to be a grand coalition of people who want to attack Scala. Since this has been going on for a while, and the points of critique are usually somewhere between unbalanced and ridiculous, I have been curious why this is. I mean you can find things that suck (by some definition of "suck") in any language, why is everybody attacking Scala? Why do you not see articles of Rubyists attacking Python or of Haskellers attacking Clojure?
Эта реакция примечательна тем, что в ней нет ни малейшего намека на понимание ошибки отбора (selection bias). Одерски, видимо, даже не приходит в голову, что он, возможно, замечает наезды на Скалу чаще, чем наезды на другие языки программирования, и помнит о них дольше. Поскольку он не задумывается о возможной когнитивной ошибке, у него нет шансов скорректировать свое мышление. Искаженная картина мира, которую он, как ему кажется, наблюдает, приводит его к фразам, которые граничат с конспиративными теориями ("grand coalition of people who want to attack Scala").

Я регулярно читаю Hacker News и другие форумы, на которых появляются такие "наезды" на разные языки программирования. В адрес Скалы их было несколько штук за последние годы, но отнюдь не фонтан; более того, подобные наезды постоянно появляются и обсуждаются в адрес всех популярных языков, включая все те, что назвал Одерски в своем письме, и многие другие. Да что там говорить - один этот эпический наезд на Ruby on Rails несколько лет назад вызвал больше обсуждений и комментариев, чем все анти-Скальные записи вместе взятые.

Мой аргумент не в том состоит, что вот, какой дурак Одерски. Одерски - очень умный и талантливый человек. Суть в том, что ошибка отбора - это нечто фундаментальное и повсеместное, что грозит нашему мышлению каждый день по сотне поводов, и следует сознательно о ней помнить и сознательно себя проверять. Я не ожидал того, что Одерски, учитывая его долгую карьеру и ведущую роль в разработке и продвижения Скалы, этого не понимает.
Цитирую из подзамочной записи с разрешения автора, который работает в американской компании и интервьюирует программистов:
Интесная закономерность выявляется. Мы начинаем интервью с того, что просим кандидата прочитать вот такой код, и сказать, что он делает. Как бы он назвал эту функцию?

private static int ok(int a, int b) {
   while (a >= b) a -= b;
   return a;
}

Пока результаты такие, что после этого вопроса интервью можно заканчивать. Если человек отвечает нормально на этот вопрос, то и дальше отвечает нормально. Если вообще близко не может понять о чем речь, то дальше только хуже.
Странное дело - по опыту интервьюирования в последнее время, кандидаты почти всегда хорошо знают, что такое мьютексы, семафоры и критические секции, зачем они нужны и какие есть основные предосторожности в работе с ними; но мало кто почти никто не знает, что бывает atomic increment (и другие атомарные операции) и как ими пользоваться. Я почему-то думал, что это знание примерно одного уровня и источника.

(точнее, фразу atomic increment знают, но думают, например, что это работает "через мьютексы" или "с помощью OS")

March 2014

S M T W T F S
       1
2 3 4 5 6 7 8
9 10 11 12 131415
16171819202122
23242526272829
3031     

Syndicate

RSS Atom

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 22nd, 2017 10:21 pm
Powered by Dreamwidth Studios