Con Colivas и планировщики в Linux

http://romaha.livejournal.com/

 

Не так давно в комментариях к моему посту [info]al_zatv написал: «Читал недавно про дядьку, который обиделся что его крутой планировщик задач выкинули из ядра линукс и заменили на почти такой же только хуже. Мотивировали тем, что этот дядька хирург и может бросить поддерживать свой планировщик». Информация заинтересовала. Что за человек? Что за планировщик такой он написал?

Для тех кто не в курсе, планировщик (sheduler) наверное самая ключевая технология в современных операционных системах. Очень упрощенно ее можно объяснить так. Если один процессор может обрабатывать только одну инструкцию за определенный момент времени, то как же организовать многозадачность? Очевидно, что надо выполнять их попеременно, так, чтобы у конечного пользователя сложилась иллюзия, что все выполняется одновременно. Указанная задача как раз и возлагается на планировщик.

Появление мультиядерных процессоров на рядовых персональных компьютерах явилась, по большому счету, большой неожиданностью. Для конечного пользователя всегда считалось более значимым увеличением тактовой частоты — поскольку именно с ней как-то ассоциировался рост производительности: 4 мегагерца, затем 12, 16, 33, 40, 66, 90, 100, 133, 150, 200, 233, 300, 500… Для тех кто был в компьютерной «теме» с начала 90-х и с интересом следил за прогрессом — это не просто цифры, расположенные в прогрессии, это этапы. Сейчас же акцент делается более на архитектуру, нежели на частоту. Многоядерность теоретически должна была бы привести к увеличению производительности кратному количеству ядер. Но этого не не произошло.

Самое большое разочарование, которое постигло меня в последнее время на компьютерном фронте заключалось в следующем. В систему под управлением Висты пролезли вирусы. Жена с работы на флэшке принесла. Порывшись по сети в поисках пиратских ключей к Касперскому, я плюнул и взял лицензионный интернет-секьюрити. Во время прогона теста антивирусного сканера система с 4-мя гигабайтами памяти и 4-мя ядрами и одним из самых шустрых на сегодняшний день жестких дисков встала на колени! Интерфейсное окно сканера отвечало на клик мышью через минуту, что-то запустить типа браузера или ворда было просто не реально. А где же преимущества многоядерной архитектуры? Где плавность работы в независимости от сложности фоновой задачи, коей, в жизни рядового пользователя являются архиваторы и антивирусы? Не знаю точно, какая совокупность технических недостатков привела к такому характеру работы Висты, но думаю, что несовершенство планировщика играло здесь не последнюю роль.

Плюнув в открытое окно реестра, я пошел в магазин, купил еще один винт на 500гб и поставил на него Ubuntu, в окончательном намерении сделать Линукс единственной своей операционной системой, а винды переустановить и оставить жить только во имя игрушек. То есть фактически пребывать в состоянии анабиоза.
Линукс я люблю за то, что он сам по себе еще та игрушка, по интересности не уступающий лучшим представителям квестов или рпг, а по накалу страстей сравним с шутером. Чтобы испытать указанную гамму эмоций я полез ему в кишки.

Вчера, придя наконец-то с работы, я узрел две новости, которые не могли оставить меня бездеятельным. Первая была на виду — вышла стабильная версия ядра, 2.6.31. Вторая новость была не такая заметная, но я обратил на нее внимание. Под эту версию появился патч, меняющий штатный планировщик на Brain Fuck Scheduler. Ничего так название, да? Оказывается, что автор этого патча (т.е. планировщика), чел по имени Con Kolivas, который, как следует из Википедии, австралийский анестезиолог, известный программистской работой над лиуксовым ядром.

То есть тот самый, про которого говорил [info]al_zatv. Чел действительно интересный. Как я понял, целью его патчей было улучшение работы именно десктопных систем, и улучшение планировщиков стояло первоочередной задачей. Но по законам жанра, если есть герой, то обязательно найдется и антагонист, коим в данном случае оказался программист Red Hat – Ingo Molnár. Последний вдохновился работами Коливаса, и разработал свой планировщик – Completely Fair Sheduler, алгоритм который был включен в ядро. В 2007 года Коливас объявил, что сворачивает деятельность по программированию в сфере ядра Линукс. Одной из причин он назвал разочарование, что при разработке ядра не отдают должного интерактивности десктоп-окружения. Ну и по человечески понятно — обидно, когда твои работы не получают должного признания.

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

 

Почему я ушел.

Линукс переполнен корпоративным хламом, и это делает его слабым в роли десктоп-системы, считает кернел-хакер Кон Коливас, который объявил о своем уходе после нескольких лет работы над улучшением ядра Линукса.

Кон Коливас — заметный кернел-хакер, приверженец использования Линукса в качестве десктопной операционной системы. Но почему он решил оставить разработку ядра?

Получить информацию из «первых уст» довольно трудно, поскольку основным видом его деятельности является работа анестезиолога в больнице, а разработка ядра Линукс просто хобби.
Несмотря на это, Кон Коливас — имя хорошо известное в свете разработки ядра Линукс и для этого есть веские причины. Его сосредоточенность именно на производительности ядра операционной системы на десктоп-системах привело к появлению толпы поклонников и его патчи для ядра (помеченные как -ck) имели заметное влияние на развитие ядра в целом. Некоторые его изменения были прямиком включены в ядро, а другие вдохновили других разработчиков на изменения, который продолжают вноситься в ядро и по сей день.
В интервью приводятся причины, по которым Коливас оставил разработку, а также его точка зрения о будущем ядра Линукс.

Смерть инноваций на PC и как Кон Коливас начал замечать проблемы произодительности на десктопной Линукс-системе.

APC: Как ты начал участвовать в разработке ядра? Получал ли ты от этого удовольствия и что тебя вообще подвигло?

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

Первый мой компьютер появился у меня в 24 года. Тогда история PC только начиналась и было интересно, в каком направлении она будет двигаться. Все были в предвкушении того, что будет впереди, ожидали новых разработок.

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

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

Приоритет «железа», двигающий компьютерные разработки, порой приводил к неудачам в силу слабого маркетинга, ошибок разработчиков, и многих других проблем. А сейчас софт стал королем горы и железо просто старается ему соответствовать.

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

Когда так происходит, железо начинает выполнять обслуживающую функцию по отношению к операционной системе. Такое положение вещей сложилось в 1994 году и действительно по сей день.. Еще хуже, что производители железа медленно поглощают друг друга, уменьшая для пользователя возможность выбора. Выпускаются просто более быстрые и мощные версии того, что было прежде. В результате сложилась ситуация, когда более быстрые процессоры, большие объемы оперативной памяти, дискового пространства и мощные видеокарты нужных только для обслуживания операционных систем. Просто разработка инновационного железа больше не воспринимается рынком. На это нет денег. Для этого нет рынка. Компьютеры стали скучны.

Перейдем к Линуксу. Мы все знаем, что он начался как хобби. Мы все знаем, что он вырос в нечто настолько большее, чего ни кто не мог представить. Можно сказать, что сейчас Линукс один из самых важных из очень малого числа конкурирующих на рынке операционных систем игроков, в то время как рынке имеется стандарт де-факто — MS Windows (который как я считаю, является таковым незаслуженно). Если бы разработка инновационного железа по-прежнему была движителем разработки и соперничества операционных систем, у Windows не было бы столько пользователей, разработчиков, а главное время, чтобы стать тем, чем она является сейчас – стандратом. Железо очень мало изменилось за это время. PC конечно стали невообразимо мощнее по сравнению с теми, которые имелись в 1991 году, когда впервые был загружен Линукс. Но это следствие увеличившейся скорости, а не функциональности или инновационности.

Так что не так с PC? Считаю, что PC умерли со всех точек зрения 20 лет назад. Сейчас мы знаем, что PC – хлам и в обозримом будущем все окружение, способы обработки информации, коммуникации останутся теми же. Интернет упрочил позиции PC.

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

Тем не менее, PC — хлам. Это мусор. Во всех сферах применения, которые важны для нас, все оказывается перегруженным и слишком медленным. Сегодня у нас есть персональные компьютеры, которые по производительности равны суперкомпьютерам десятилетней давности. Десять лет назад у нас были персональные компьютеры равные суперкомпьютерам двадцатилетней давности и так далее. Так почему же все так тормозит? Если компьютеры становятся быстрее, почему на запуск системы и запуск приложений требуется больше времени чем раньше? Нет, когда они заняты чистой обработкой информации (типа декодирования видео) они восхитительны. Но во всем остальном сегодняшние компьютеры невероятно медленны. Они могут быть в 1000 раз быстрее чем они были декаду назад, и все по прежнему будет работать медленно.

Обычный аргумент который мне приводят люди в ответ — но ведь сейчас компьютеры делают намного больше чем раньше, поэтому это нечестное сравнение. Ладно, но они в 10 раз медленнее вместо того, чтобы быть в 1000 раз быстрее, следовательно они должны делать больше в 10000 раз. Очевидно, что те 10000 раз что они делают, они делают где-то не там, где нужно.

APC: Так значит проблемы производительности в Линукс на десктоп-системе стали для тебя главным мотиватором?

Да. Я начал с улучшения Линукса на десктопе, думая – «если я могу контролировать весь софт, я смогу заставить работать его быстрее». Должен же быть путь настроить, оптимизировать и добиться лучшей производительности. Возможности что-то улучшить в области работы пользователя были очень ограничены, когда я начал работать с Линуксом. Он вообще едва работал на десктопе, и попытка улучшить что-то с целью ускорения, приводила к тому, что вообще ничего не работало. Наследие Unix было налицо. Мы приспосабливали операционную систему не предназначенную для десктопа и этот процесс был болезненным.

Постепенно я заметил, что изменения в ядре ведут к увеличению в скорости. Изменения не были огромными, но они влекли за собой слегка заметные изменения в таких вещах как поведение процессора под нагрузкой и тому подобное. Первый патч, который я вынес на публику не содержал моего собственного кода и был для ядра 2.4.18 . Было это где-то в феврале 2002. Я даже не знал, что представляет из себя код C, поскольку никогда не изучал какую-либо компьютерную науку. Из-за этого я застрял на месте до момента, когда ядро 2.6 было в разработке. Я следил за ее ходом и буду честен – я ужаснулся! Те разработчики ядра которых я уважал, работали над каким-то корпоративным хламом, который совершенно не нужен обычным пользователям.

И что хуже всего, хотя мне и нравится видеть Линукс на машине с 1024 процессорами и 1000 жестких дисков, мне противна мысль, что такая возможность, включенная в ядро, может убить производительность настольной системы.

Если количественные показатели это все что мы знаем, измеряя производительность, то действительно, она лучше чем когда либо. Но запускаем аудио-плеер и он заикается. Заикается! У нас черт знает сколько мегагерц, а мы не можем заставить нормально играть аудио?

Или начните записывать большой файл на диск и в это время только курсор будет двигаться, а все остальное на рабочем столе будет мертвым, а окна не будут обновляться в течение минуты.
Я чувствовал, что готов заплакать.

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

Все разработчики делают что-то, что не имеет ничего общего с десктоп-системой. Они все являются работниками больших компаний, которых не заботят проблемы обычных пользователей. Все, что их волнует — 1% лишний процент производительности, полученный в своем бенчмарке базы данных.

Линукс победил. Мы огромный конкурент на рынке серверов и баз данных и все большие компании проявляют заботу о Линуксе. Деньги текут разработчикам и они улучшают производительность системы в тех областях, в которых нужно заказчикам.

Пользователи проиграли. Обычный настольный компьютер для которого изначально разрабатывался Линукс остался в стороне. Производительности, в том виде, в каком ее понимают обычные пользователи, больше нет. Хуже того, мы даже не может ее измерить, чтобы что-то доказать. Единственное место, где я нашел возможность улучшить производительность — ядро. Разработка которого тоже начала движение в обратную от интересов пользователя сторону.

APC: И что ты сделал чтобы попытаться убедить разработчиков ядра сфокусировать свои усилия на нуждах простых пользователей?

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

У меня уже был опыт создания патчей для предыдущего ядра и по иронии судьбы они были связаны именно с планировщиком. Хотя я никогда не учился программированию, код перед моими глазами постепенно начинал наполняться смыслом.

Я перестал указывать людям, о том, что я думаю: в каком именно участке кода имеется проблема. После жалоб, упреков и указаний, я решил, что должен сам начать копаться в коде и пытаться сделать все самостоятельно.

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

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

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

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

APC: А что из твоего кода было включено в официальное ядро?
Оглядываясь назад, на то время, когда мои патчи были на слуху, могу сказать что в действительности мало что из моего кода было включено в официальное ядро, хотя это вызвало интерес к разработке у других людей. Большей частью мой код коснулся планировщика в плане улучшений таких свойств как interactivity, fairness, SMP user fairness, hyperthread fairness и некоторых других. Было также множество более мелких изменений в разных областях — в подсистеме виртуальной памяти, отложенных вызовах, планировании работы подсистемы вовода-вывода и случайные баг-фиксы.

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

APC: Какова была расплата твоего участия в разработке?

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

APC: Что было главной силой, которая привела к тому, что бы забросил клавиатуру разработчика и наборы патчей «-ck».

Это один из вопросов про которые хочется сказать – «жалко что я не получаю монету каждый раз, когда мне его задают»

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

Первая причина — забава. Я всегда был компьютерным гиком и мне нравилось проводить часы перед компьютером делая… да без разницы чего. И поэтому проводить время делая что-то, что является твоей страстью, является очевидным источником удовольствия.

Вторая — интеллектуальное испытание. Были вещи, которые я считал, должны быть сделаны в ядре, и были люди которые не считали нужным заниматься этим. Хотелось столкнуться с ними лицом к лицу и сделать что-то, что я никогда не делал, особенно в области “высокого программирования”. Я узнал очень много о разработке операционных систем, познакомился с основами компьютерных наук, которые большинство студентов соответствующих факультетов возможно считают очень скучными.

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

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

APC: И ты нашел этот баланс?

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

Ну а третья причина — это эго. Если я исправлял что-то, что меня заботило, обычно оказывалось, что есть масса людей, которых это заботило также как и меня. Причина этого была в том, что я был обычным пользователем, который, в то же время, претендует быть кернел-хакером. И если я привносил изменения, которые затрагивали таких же обычных пользователей, то это заботило очень многих. Я вспоминаю одного известного разработчика, которого я очень уважаю – он шутил о моих «фанатах», спрашивая, как я могу так увлекать толпу? Он внес в ядро возможно в 1000 раз больше строчек кода, а «последователей» имел я.

Но привлекал я пользователей только потому что работал над тем, что меня заботило. Вещь, которая заставляла меня вести разработку, было просто «спасибо», которое я получал от пользователей -ck патчей.

Но я все еще не ответил на вопрос, что заставило меня прекратить работу над ядром. Я думаю, что объяснение мотивов почему я делал, помогут объяснить почему прекратил.

Интеллектуальное испытание — да, оно все еще было.

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

APC: А что послужило «последней соломинкой» для тебя?

Главный отказ о включении моего кода в ядро, который я получил, касался моего планировщика. Он был гораздо лучше в вопросах интерактивности, хотя тоже был не идеален. Пока я продолжал работать над ним, фокус главных маинтейнеров сместился от планировщика к другим вопросам. И причиной, по которой Алан Мортон отказал в включении моего кода было то, что есть более срочные вопросы и ошибки, которые нужно исправить в ядре. Это действительно было так. Но всегда есть множество подсистем в ядре, которые постоянно переписываются и в них обнаруживаются недостатки. А ведь постоянное их переписывание более важно, чем улучшения, касающиеся вопросов работы десктопа, так?

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

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

Целью разработанного Plugshed было обеспечение интеграции нашего планировщика в код ядра. Не знаю насколько это правильно, но многие люди продолжают идти таким путем.
Потом началась работа касательно функции swap prefetch. Я потратил много времени для ее улучшения. Они была включена в ядро 18 месяцев назад и с тех пор я работал над ней.
Андрю не считал, что эта функция полезна и полагал, что она может вызвать негативные последствия. Но за последние 9 месяцев не было баг-репортов или жалоб на падение производительности из-за нее. Я написал бенчмарк, который показывал, как это работает. Но Линус спросил меня «Да, но оно правда помогает?» Отчеты пользователей и показателей бенчмарка тоже было недостаточно. Хорошо хоть они просто не выкинули функцию из ядра.

Теперь о планировщике Staircase Deadline CPU. Сначала работа над ним началась как ответвление от Staircase CPU. Но вскоре я понял, что он обеспечивает превосходную интерактивность, и даже возможно решить проблемы с «честностью», поскольку улучшение интерактивности часто является причиной ухудшения «честности». Ну а честность первостепенна для серверов и систем с большим количеством пользователей.

Многие пользователи посылали просьбы «протолкнуть» планировщик в основной код, поскольку он исправлял многие недостатки… и даже был пользователь, который требовал от Линуса сделать это выпустив баг-фикс для основного ядра настолько быстро, насколько это возможно. Тем временем я улучшал код и исправлял некоторые ошибки.

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

Я лежал и думал, что я делал и почему. Но решил довести работу над планировщиком Staircase Deadline. А потом я вышел из работы навсегда.

Добавить комментарий

Войти с помощью: