Обновить
9

Пользователь

24
Подписчики
Отправить сообщение
как они там у себя детей сортируют от меньших к большим
пузырьком
Честно говоря, это какая-то дичь. Интеллектуальной собственностью, несомненно, являются конкретные реализации — например, VHDL/Verilog исходник процессора, или фотографии поверхности чипа, или какие-то алгоритмы, например, предсказания ветвлений, которые не описываются в публично доступной документации, или недокументированные регистры MSR, и т.д. Т.е. все, что не является частью публично доступной документации, которую Intel раскрыла по своему собственному желанию.

Но набор инструкций является, фактически, API к чипу. Согласно решению, которое Верховный Суд вынес в деле «Oracle против Google» касательно открытой реализации Java API, любой может реализовывать публичный API любого продукта самостоятельно, не опасаясь преследований со стороны автора этого API, так как подобное использование считается добросовестным (fair use).

Если бы это было не так, то любые альтернативные реализации WinAPI или их частей, такие как Wine/Crossover/ReactOS, могли бы преследоваться Microsoft, тем самым убивая возможность создания открытых альтернатив. Несмотря на то, что я не фанат Microsoft, я надеюсь, они подадут ответный иск и постараются его выиграть, чтобы укрепить еще одним прецедентном возможность создавать открытое ПО.

Пожалуй, вам не стоит больше заниматься машинным обучением.

Пардон, я не увидел флажок "из песочницы". Приношу извинения, я был не прав.

Код на любом языке программирования, включая ассемблер и APL, будет проще и понятнее, чем "SPL".

Спасибо за публикацию статьи

А вы не обделены скромностью.

А зачем нужен этот язык? Какие он задачи решает, с которыми не справляется Python, JS, Lua, Ruby, bash?..

Скорее бы уже наконец-то запретили интернет полностью.

Пример с async-функцией лучше написать без await-ов, оставив await-ы на как можно позже в цепочке вызовов — когда результат на самом деле нужен. Разница заключается в том, что если промис не await-ить, то родительская функция не заблокируется, и тем самым несколько промисов будут исполняться параллельно (но не одновременно, конечно же).


Следующий код демонстрирует разницу в два раза во времени выполнения между функцией, где все промисы сразу await-ятся, и между функцией, в которой await откладывается до последнего.


Скрытый текст
function delay(timeout) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, timeout * 1000);
    });
}

async function getValueForA() {
    await delay(1.0);
    return 1000;
}

async function getValueForBFromA(a) {
    await delay(1.0);
    const b = (await a) / 5;
    await delay(1.0);

    return b;
}

async function getValueForC() {
    await delay(1.0);
    return 30;
}

async function getValueForDFromB(b) {
    await delay(1.0);
    const d = (await b) / 50;

    return d;
}

async function calculateTotal(a, b, c, d) {
    return (await a) + (await b) + (await c) + (await d);
}

async function doSomethingA() {
    const a = await getValueForA();
    const b = await getValueForBFromA(a);
    const [ c, d ] = await Promise.all([
        getValueForC(),
        getValueForDFromB(b),
    ])
    const total = await calculateTotal(a, b, c, d);
    return total / 1000;
}

async function doSomethingB() {
    const a = getValueForA();
    const b = getValueForBFromA(a);
    const c = getValueForC();
    const d = getValueForDFromB(b);
    const total = await calculateTotal(a, b, c, d); // только тут!
    return total / 1000;
}

async function timeit(times, func) {
    const start = process.hrtime();
    for (let x = 0; x < times; x++) {
        value = await func();
    }
    const [diff_s, diff_ns] = process.hrtime(start);

    return [diff_s * 1000000000 + diff_ns, value];
}

async function main() {
    const rep = 1;
    const [[At, Av], [Bt, Bv]] = await Promise.all([timeit(rep, doSomethingA), timeit(rep, doSomethingB)]);

    console.log(`A: (==${Av}) ${At}`);
    console.log(`B: (==${Av}) ${Bt}`);
    console.log(`d: ${At/Bt}`);
}

main()
Нет никаких доказательств что Вы не ходите по ночам в костюме клоуна.
Еще бы — я стараюсь не оставлять свидетелей.
Нет никаких доказательств, что это настоящие деньги, а не своеобразный «демосчет».
В JS изначально даже var не было, да и сейчас практически все резольвятся в рантайме, поэтому я бы не стал брать JS в качестве примера как надо делать типизацию.

В JS изначально много чего не было. Тот JS, который имеем сейчас, и тот, с которого начиналось, это два разных языка, с разными ценностями и идиомами. И современный JS семимильными шагами идет к сильной типизации с выведением типов.


в nsynjs свой event loop, а также свои структуры с программными счетчиками, стеками, локальными переменными, closures и т.п.

И все это, конечно же, неявное. И, кстати, зачем это все нужно, ведь рантайм уже все предоставляет?


Имеется ввтиду внутри промисифицированных функций, или если промис вернули куда-то в не async-функцию

Если вернули не в async-функцию, она с ним работать все равно не сможет, поэтому и исключение ловить не надо, т.к. исключение все равно не будет выброшено в контексте этой функции.


в том что есть указатель на ее состояние, с её собственным event-loop-ом, по которому над ней можно иметь полный контроль.

Насколько мне известно, запустить несколько event loop в одном потоке нельзя по определению этого самого event loop, т.к. каждый event loop должен выполнять ожидание событий на своем списке дескрипторов средствами операционной системы. Значит, каждая функция работает в отдельном потоке? Великолепно! И в таком случае, в чем отличие от WebWorkers? И как у вас решился вопрос отсутствия в JS любых механизмов многопоточной синхронизации?


В блюберд придется писать код чтобы отслеживать активные промисы. Хотя это и не сложно. В нативных промисах этого нет, и, говорят, не будет.

Имеющийся proposal был отозван из-за излишней сложности реализации в v8, насколько мне известно. придумают способ проще — будет.


Это придется делать везде, где вызывается промис с setTimeout? Либо делать async-обертку к промису, ну и отслеживать активные обертки. В nsynjs это делается автоматически, т.к. есть свой стек, по которому можно всегда узнать что сейчас активно.

"Explicit is better than implicit. Simple is better than complex." Я не понимаю, в чем проблема явно освободить занятый ресурс (да, таймер это ресурс), как не вижу проблемы в том, чтобы закрыть за собой сокет или файл. Что делать, если я хочу из nsynjs передать объект таймера за пределы вашей RAII-процедуры? Мне его убьет при выходе из процедуры, несмотря на то, что референс утек? Если не убьет, тогда в чем смысл? Если убьет, то как этим пользоваться?


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


Мне бы хотелось больше узнать о мотивации, зачем это было сделано, и какие именно задачи это призвано решать, потому что, как мне кажется, очевидно, что с async/await это решение не конкурент.

— в nsynjs нет надобности использовать ключевые слова async/await в коде, так как тип исполняемой функции проверяется в рантайме

и это плохо. Javascript неспроста движется в сторону проверки всего и вся при компиляции, включая статическую типизацию.


— в nsynjs отпадает надобность в промисах в принципе (хотя для поклонников можно добавить несколько строчек в код nsynjs чтобы проверять возвращаемый функцией результат в рантайме на предмет не промис ли он, и не надо ли подождать).

прелесть промисов в явном, детерминированном управлении event loop — см. концепции greenlets, fibers и т.д. В nsynjs этого нет, и по дизайну невозможно.


— в nsynjs для исключительных ситуаций достаточно механизма try/catch/throw. Механизм Promise/then/catch/reject не нужен.

Наверное, я неправильно использовал промисы все это время?


async function foo() {
    try {
        await bar();
    } catch(e) {
        // ...
    } finally {
        // ...
    }
}

— возможность запускать псевдо-потоки,

В чем отличие от запущенной async-функции?


— возможнось останавливать псевдо-потоки как изнутри, так и извне,

В чем отличие от bluebird, который умеет отменять исполняющиеся промисы?


— возможнось подчистить активные функции с колбеками при остановке потока извне (например на активный setTimeout автоматически вызвать clearTimeout),

В чем отличие от обертки try/finally внутри тела async-функции, с clearTimeout внутри finally?


— возможность создавать конструкторы с асинхронными функциями внутри.

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

Я согласен — раз уж умнейшие люди из крупнейших IT-компаний приняли такое решение, то мои вопросы автоматически стали глупыми и непрофессиональными. Наверняка ответ есть, дорасту — узнаю.

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

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


Если хранить все в одном гигантском репозитории… я не знаю, я не могу придумать плюсов такому решению. То, что предлагается как плюсы в гугловском документе, мне кажется достаточно надуманным:


Unified versioning, one source of truth;

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


Extensive code sharing and reuse;

Что мешает реюзать код в распределенном окружении? Если какой-то код используется в двух проектах, то он должен быть вынесен в библиотеку, а не скопирован. У этой библиотеки свой репозиторий, своя версия, свои зависимости.


Simplified dependency management;

Я понимаю, к чему это — вместо того, чтобы перечислять зависимости явно, там, скорее всего, здоровенный список "давайте любой код будет зависеть от libcommon, в которую включено все, что у нас только есть". Хороший ли это подход? Я думаю, это омерзительный подход, так как в libcommon вносятся несовместимые изменения, то как узнать, что именно нужно чинить?


Atomic changes;

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


Large-scale refactoring;

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


Collaboration across teams;
Flexible team boundaries and code ownership;

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


Code visibility and clear tree structure providing implicit team namespacing.

Тут мне на ум приходит только цитата Гвидо ван Россума, одного из сотрудников Гугл — Explicit is better than implicit. Simple is better than complex. Flat is better than nested. Sparse is better than dense.. Если деление на команды все равно происходит неявно на уровне структуры репозитория, зачем делать это одним репозиторием, когда это УЖЕ логически разделяет репозиторий на подрепозитории?


Так много вопросов, так мало ответов.

Похоже, ребята из Microsoft не до конца разобрались с тем, как этим пользоваться. Или, возможно, их код страдает от сильной связности, поэтому нельзя сделать какие-то изменения только в одном компоненте — нужно делать pull request в сотне репозиториев одновременно, а это неудобно и приводит к ошибкам.

Это репозиторий с git. Хотелось бы видеть https://github.com/Microsoft/Windows/, о котором шла речь в статье.

Не увидел в статье ссылки на репозиторий.

И как, появилась?

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Архитектор программного обеспечения