LINUX.ORG.RU

Ant: создание среды выполнения JavaScript за один месяц

 , , , ,


1

3

Это перевод поста building a javascript runtime in one month от второго января 2026 года.

TLDR: Я создал Ant, небольшую (2 МБ) среду выполнения JavaScript. Полный исходный код, а также тесты и документацию можно найти на моем github.

Когда я начал этот проект в начале ноября, у меня была простая идея: а что, если я смогу создать движок JavaScript, достаточно маленький, чтобы его можно было встроить в программу на C, но достаточно полный, чтобы на нём можно было запускать реальный код? Что-то, что можно было бы распространять, не таская с собой сотни мегабайт V8 или Node. Я уже пробовал это раньше с минимальными копиями Deno, но этого было недостаточно.

Я не думал, что это займет месяц. Я не думал, что это будет возможно за месяц. Но вот в чём дело – когда создаёшь что-то без сроков, ты просто продолжаешь работать.

Первая неделя была режимом выживания

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

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

Знаете ли вы, что автоматическая вставка точки с запятой является фактической частью спецификации, с которой вам приходится иметь дело?

Знаете ли вы, что биндинг this меняется в зависимости от контекста, и что предварительное объявление означает, что переменные, объявленные с помощью var, существуют до того, как им присваивается значение? Даже window.window.window является действительным…

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

typedef uint64_t jsval_t;

Каждое значение JavaScript в среде выполнения представляет собой одно 64-разрядное целое число. NaN-боксирование. Спецификация IEEE 754 с плавающей запятой имеет странный пробел: существует 2^53 возможных значений NaN, и большинство из них никогда не используются. Поэтому я их украл :3.

Если значение выглядит как NaN при интерпретации битов как double, то экспонента и мантисса следуют заданному вами шаблону, и вы можете закодировать тег в этих битах. У вас есть место для указателя и типа. Вы упаковываете ссылку на объект и тег в 64 бита. Внезапно каждое значение JavaScript помещается в одно машинно-ориентированное слово.

Проверки на этапе компиляции доказывают это:

_Static_assert(sizeof(double) == 8, "NaN-boxing requires 64-bit IEEE 754 doubles");
_Static_assert(sizeof(uint64_t) == 8, "NaN-boxing requires 64-bit integers");
_Static_assert(sizeof(double) == sizeof(uint64_t), "double and uint64_t must have same size");

Это стало основой того, как среда выполнения представляет каждое отдельное значение. Каждое число, каждый объект, каждая строка, каждая функция, каждое promise, каждый аргумент, каждая область действия. Всё является одним из них. Никаких дискриминируемых объединений, никаких vtable, никаких выделений кучи для метаданных. Только биты. Потребовались дни итераций, чтобы дойти до этого, но как только это заработало, всё остальное стало быстрее. Значения NaN и Infinity имели свои собственные проблемы, но небольшая перестановка боксирования помогла их исправить.

Примерно на четвёртый день я заставил работать переменные. На пятый день – функции. На шестой день я смог запустить циклы. Первые коммиты разбросаны. Вскоре после этого я добавил стрелочные функции, iife, опциональное цепочечное соединение и даже операторы nullish coalescing. Я перескакивал между функциями, потому что просто читал MDN, добавляя вещи по мере того, как вспоминал об их существовании.

Катастрофа со сборкой мусора

И тогда это случилось: управление памятью.

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

Я очень мучился на этом этапе. Ручной free-list GC отключался и включался сотни раз, и каждая попытка ломала ещё одну важную часть. Были дни, когда я был явно разочарован. В 3 часа ночи я занимался отладкой, пытаясь понять, почему стеки сопрограмм не защищались должным образом? Почему происходила утечка памяти? Почему все ломалось, когда я добавлял поддержку json?

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

Promises были совсем другим делом

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

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

Если посмотреть, то в коммитах видно, как это было сложно: «async promise pushback», «segfault when event loop empty», «prevent dead task from blocking». Это проблемы, которые невозможно предвидеть, пока не дойдёшь до середины реализации.

Сложность заключается в том, что promises JavaScript не могут быть простыми. Они должны обрабатывать цепочки .then(), они должны правильно отклонять, они должны работать с асинхронными функциями, которые являются всего лишь синтаксическим сахаром над генераторами, которые являются всего лишь синтаксическим сахаром над promises и обратными вызовами.

Примерно на десятый день я подключил minicoro для поддержки сопрограмм. Это решение, вероятно, спасло весь проект. Minicoro – элегантная реализация. Вы определяете сопрограммы на основе стека и позволяете системе переключаться между ними. Как только у меня появились сопрограммы, я смог реализовать асинхронную работу.

typedef struct coroutine {
  struct js *js;
  coroutine_type_t type;
  jsval_t scope;
  jsval_t this_val;
  jsval_t awaited_promise;
  jsval_t result;
  jsval_t async_func;
  jsval_t *args;
  int nargs;
  bool is_settled;
  bool is_error;
  bool is_done;
  jsoff_t resume_point;
  jsval_t yield_value;
  struct coroutine *prev;
  struct coroutine *next;
  mco_coro* mco;
  bool mco_started;
  bool is_ready;
} coroutine_t;

В этой структуре отслеживалось всё, что касалось асинхронного выполнения: область действия, значение this, ожидаемое promise, наличие ошибок. Затем мне нужно было только запланировать эти действия и управлять циклом событий.

Как только у меня появились сопрограммы, promises стали реальностью. Цепочка .then() заработала, await действительно приостанавливала выполнение и возобновляла его позже, асинхронная сторона среды выполнения начала складываться. Я начал добавлять надлежащую обработку promises, и все встроенные функции Promise появились после этого, и они появились быстро, потому что сложная часть была решена.

Странные крайние случаи JavaScript

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

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

Знаете ли вы, сколько способов доступа к цепочке прототипов предоставляет JavaScript? __proto__, Object.getPrototypeOf(), Object.setPrototypeOf() и внутренний слот [[Prototype]]. Вы должны обрабатывать все из них, и они должны правильно взаимодействовать друг с другом. Обманчиво короткий коммит под названием «use descriptor tables for getters/setters/properties» представляет собой недели работы, чтобы правильно обработать это.

Деструктуризация казалась простой: const [a, b] = arr. Но как быть с разрежёнными массивами? С перечисляемыми свойствами объектов? С вложенной деструктуризацией? Со значениями по умолчанию? Параметрами ...rest? Каждое исправление, кажется, приводит к появлению другого, и каждое из них – это «кроличья нора» крайних случаев.

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

Во второй половине всё стало странным

Ко второй неделе у меня была рабочая среда выполнения JavaScript, которая могла выполнять код. Она не была завершена, но была реальной. Затем я начал добавлять всё то, что делает её полезной.

Операции с файловой системой, утилиты для работы с путями файлов, модуль url и всеми любимый встроенный http-сервер, который сделал Bun популярным. Внезапно с Ant стали работать настоящие программы. Вы могли бы написать веб-сервер, используя только это:

import { join } from 'ant:path';
import { readFile } from 'ant:fs';
import { createRouter, addRoute, findRoute } from 'rou3';

const router = createRouter();

addRoute(router, 'GET', '/status/:id', async c => {
  await new Promise(resolve => setTimeout(resolve, 1000));

  const result = await Promise.resolve('Hello');
  const name = await readFile(join(import.meta.dirname, 'name.txt'));

  const base = '{{name}} {{version}} server is responding with';
  const data = { name, version: Ant.version() };

  return c.res.body(`${base.template(data)} ${result} ${c.params.id}!`);
});

async function handleRequest(c) {
  console.log('request:', c.req.method, c.req.uri);
  const result = findRoute(router, c.req.method, c.req.uri);

  if (result?.data) {
    c.params = result.params;
    return await result.data(c);
  }

  c.res.body('not found: ' + c.req.uri, 404);
}

console.log('started on http://localhost:8000');
Ant.serve(8000, handleRequest);
$ ant examples/server/server.js
started on http://localhost:8000

$ curl http://localhost:8000/status/world
Ant 0.3.2.6 server is responding with Hello world!

Это настоящий JavaScript, работающий в Ant: async/await, ввод-вывод файлов, HTTP, маршрутизация с параметрами, cетевые операции, операции со строками.

Темп работы увеличился. С каждым днём я становился всё более уверенным, работал быстрее, исправлял больше ошибок, добавлял больше функций. Затем наступила «неясная, но необходимая фаза». Я добавил поддержку прокси, рефлексию, символы и даже частные поля и методы в классах. Каждая из этих функций является функцией ECMA6+, которую почти никто не использует, но спецификация гласит, что они существуют, поэтому они должны работать.

Одна из моих любимых – атомарные операции:

const sharedBuffer = new SharedArrayBuffer(256);

const int32View = new Int32Array(sharedBuffer);
Atomics.store(int32View, 0, 42);
const value = Atomics.load(int32View, 0);
console.log('stored 42, loaded:', value);

Atomics.store(int32View, 1, 10);
const oldValue = Atomics.add(int32View, 1, 5);
console.log('old value:', oldValue);

Atomics.store(int32View, 2, 100);
const result = Atomics.compareExchange(int32View, 2, 100, 200);
console.log('exchanged, new value:', Atomics.load(int32View, 2));
$ ant examples/atomics.js
stored 42, loaded: 42
old value: 10
exchanged, new value: 200
Последняя неделя была просто домино

Как только ядро Ant заработало, сборка мусора стала стабильной, а функции promises заработали, всё остальное стало на свои места: незначительные проблемы были устранены, добавлены недостающие методы, решены крайние случаи.

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

К 28-му дню я дорабатывал то, что действительно работало. Полная среда выполнения JavaScript с поддержкой async/await, надлежащим управлением памятью, сетевыми функциями, вводом-выводом файлов и полной совместимостью со спецификациями ES1-ES5, а также случайным набором ещё более новых функций.

Я даже «вспомнил» включить оптимизацию LTO и другие флаги компилятора после того, как мне напомнили 😅.

Что случилось на самом деле

Один месяц. Ant теперь существует как среда выполнения JavaScript, которая:

  • Проходит все тесты на соответствие ES1–ES5 из набора тестов javascript-zoo. Полное соответствие 25-тилетним спецификациям JavaScript.
  • Реализует async/await с правильной обработкой promises и микрозадачами.
  • Имеет сборщик мусора, который действительно работает без утечек памяти.
  • Может запускать веб-серверы с использованием libuv (так же, как Node) для работы c сетью.
  • Может вызывать библиотеки через ffi следующим образом:
import { dlopen, suffix, FFIType } from 'ant:ffi';

const sqlite3 = dlopen(`libsqlite3.${suffix}`);

sqlite3.define('sqlite3_libversion', {
  args: [],
  returns: FFIType.string
});

console.log(`version: ${sqlite3.sqlite3_libversion()}`);
$ ant examples/ffi/basic/sqlite.js
version: 3.43.2
  • Может читать и записывать файлы, а также выполнять асинхронный ввод-вывод.
  • Имеет правильную работу областей видимости, предварительного объявления и затенения переменных.
  • Поддерживает классы, стрелочные функции, деструктуризацию, операторы распространения, шаблонные литералы, опциональное цепочечное соединение.
  • Обрабатывает необычные крайние случаи, о которых большинство людей не задумывается: присвоение __proto__, дескрипторы свойств, неконфигурируемые свойства, замороженные и запечатанные объекты. См. tests/proto.js.
  • Реализует систему модулей ES, которая может импортировать и экспортировать код.
  • Поддерживает символы, прокси, рефлексию, weakmaps, weaksets, maps, sets.
  • Поддерживает разделяемую память и атомарные операции для параллельного программирования. Прочитав это, вы понимаете, что перед вами полноценная среда выполнения JavaScript, а не просто игрушка.
Цена

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

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

В конце я сталкиваюсь с крайними случаями, которые требуют чтения спецификациё ECMAScript, понимания того, что делает V8, проверки того, как другие движки обрабатывают некоторые странные крайние случаи. Улучшение подсчета символов, оптимизация классов и даже перенос внутренних свойств в слоты (как это делает V8). Это оптимизация производительности и улучшения архитектуры, которые должны происходить только после стабилизации кодовой базы. За исключением того, что всё это происходит на прошлой неделе, потому что основа прочная, и у меня есть пропускная способность.

После выпуска: этап оптимизации

Первый релиз состоялся 26 ноября. Затем наступила тишина. Обычная тишина, которая наступает после выпуска чего-либо. Затем, около 20 декабря, работа возобновилась.

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

Я начал с добавления аллокатора арены для типизированных массивов. Раньше типизированные массивы были разбросаны по всей куче. Поэтому я их объединил, чтобы ускорить выделение памяти и улучшить локальность кеша.

Затем я перешёл на использование таблиц дескрипторов для геттеров/сеттеров/свойств. Вместо отдельных выделений для каждого дескриптора свойства я сгруппировал их в таблицы. Меньше выделений, меньше преследований указателей.

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

Я люблю таблицы диспетчеризации. Я перешел на использование вычисляемого goto для ffi, json и других. Это позволяет процессору переходить непосредственно к нужному обработчику. Устраняется ветвление, устраняется поиск.

Перенос свойств в слоты был самым инвазивным рефакторингом. Объекты использовали гибкую систему свойств, которая была правильной, но медленной. Слоты представляют собой фиксированную структуру для каждого типа объекта. Чем больше предположений может сделать среда выполнения, тем меньше косвенных ссылок.

Где-то здесь появилось сравнение с Node. Запустить те же тесты. Как справляется Ant? Результаты стали выглядеть хорошо. Очень хорошо. Настолько хорошо, что начинаешь задаваться вопросом, смогу ли я действительно превзойти Node в чём-то?

Оптимизация Ant создавала снимки рабочих версий. Если я что-то ломал при оптимизации, у меня была точка, к которой я мог вернуться. Постепенный прогресс. Каждая фиксация была немного быстрее предыдущей. Некоторые оптимизации работали, некоторые — нет. Но схема оставалась прежней: профилирование, оптимизация, измерение, коммит.

Затем последовали улучшения в работе сборщика мусора. Интеграция BDWGC работала в течение первого месяца, но где-то на этапе оптимизации она была отключена. Среда выполнения просто теряла память. Я снова добавил отложенную сборку мусора и раскомментировал большую часть старого GC.

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

Почему это случилось

Честно говоря, я не знаю. Возможно, из злости. Из потребности что-то доказать. Из чистой одержимости. Из того состояния, когда ты работаешь над чем-то и вдруг обнаруживаешь, что прошло восемь часов, уже 4 утра, и ты просто фиксируешь код и завтра делаешь то же самое.

Проект существует, потому что что-то во мне решило, что он должен существовать, и не остановилось, пока это не произошло.

Он не идеален. В коде, вероятно, есть ошибки, которые я не обнаружил. Вероятно, есть проблемы с производительностью, которые я не оптимизировал. Вероятно, я пропустил некоторые требования спецификации. Но он работает. Вы можете писать настоящий JavaScript, и он будет выполняться. Вы можете использовать async/await. Вы можете создавать серверы. Вы можете использовать его для реальных задач.

Если вы когда-нибудь задумывались, что может сделать один человек, обладающий достаточной решимостью и не имеющий графика сна, то ответ – совместимый движок JavaScript. Вот что возможно.

★★★★★

Проверено: maxcom ()
Последнее исправление: dataman (всего исправлений: 1)

Название неудачное, потому что уже занято. Ant - это система сборки кода на Java.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Название неудачное, потому что уже занято. Ant - это система сборки кода на Java.

Java, JavaScript - какая разница 🤷

п.с. вообще тоже про него подумал

frunobulax ★★★★
()

движок JavaScript, достаточно маленький, чтобы его можно было встроить в программу на C

Кощунство какое-то.

Zhbert ★★★★★
()

Похоже setTimeout неправильно передаёт/обрабатывает параметр задержки.

setTimeout(() => console.log(1), 1000)

При таком вызове результат попадает в консоль моментально, никакой секундной задержки не заметно.

Проверил на сборке из master и скаченной с github.

Ja-Ja-Hey-Ho ★★★★★
()

Простая арифметика грит, что автор писал 70 строк в час, если учесть, что он при этом вообще никаких исследований и отладок не проводил. Общая статистика даж веселее:

theMackabu <theMackabu@gmail.com>:
	  insertions:    125035	(100%)
	  deletions:     35007	(100%)
	  files:         2833	(100%)
	  commits:       710	(100%)
	  lines changed: 160042	(100%)
	  first commit:  Wed Nov 19 14:28:06 2025 -0800
	  last commit:   Wed Feb 4 20:02:51 2026 -0800
2000 строчек в день, 270 строчек в час. Мне бы так.
https://bykozy.me/static/ant_repo_stack_plot.png

Логичное замечание при чтении кода — кто эту срань после автора будет поддерживать?
https://bykozy.me/static/ant_diff.png
https://bykozy.me/static/ant_diff2.png

У меня тоже была идея запилить что-то своё новомодными ИИ, но каждый раз возникало понимание, что это будет очередной огрызок на 90% такой же, как аналогичные огрызки.

Мне нейросетка подсказала, что

Offset-based memory model (jsoff_t offsets into contiguous mem buffer)
Tagged value representation (mkval(T_OBJ, ...))
Property storage using offset chains

являются шаблонными приёмами, применёнными в куче других JS-интерпретаторов.
Например:
https://github.com/cesanta/elk/blob/a9bb85619c5cddf49dfa8bdf529770fc9943a7fd/...
сравните с
https://github.com/theMackabu/ant/blob/42e2fdb00d8b5ae39cd07a96caf77627e418ab...

Даже константы внутренние не поменял.

По этой причине в разделе «the price» автор скромно умалчивает о счёте от провайдера, который автор получил через месяц интенсивной генерации кода ИИ.

К слову, я недавно обосрал парочку аналогичных проектов, с которыми я недавно столкнулся:
https://bykozy.me/blog/state-of-decay-in-self-hosted-commenting/
У Artalk картина была аналогичная — 90% кода написано в одно рыло за несколько месяцев, и потом проект встаёт колом на одном месте...

Не знаю, грустно как-то это.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 3)
Ответ на: комментарий от byko3y

Статью писал ИИ, почему б ему и программку не сделать.

Irma ★★★
()

Не хило так человек заморочился.

P.S. Для сравнения, метациклический интерпретатор схемы занимает строк триста кода и пишется за пару вечеров человеком, который только что узнал слово «метациклический интерпретатор».

ugoday ★★★★★
()

Пост не читал, поиск по QuickJS ничего не нашёл, чем не устроило?

vbr ★★★★★
()
Ответ на: комментарий от seiken

Тоже такая же первая мысль при прочтении новости.

«ну куда он лезет, если даже базу не знает»

Saakx
()
Последнее исправление: Saakx (всего исправлений: 1)
Ответ на: комментарий от ugoday

Не хило так человек заморочился.
P.S. Для сравнения, метациклический интерпретатор схемы занимает строк триста кода и пишется за пару вечеров человеком, который только что узнал слово «метациклический интерпретатор».

При чём тут человек? Код писал ИИ, причём, либо прямо скопировав elk.js, либо косвенно нейросеть написала копию elk.js, как эталонного интерпретатора:
https://bykozy.me/static/elk_vs_ant.png

Вот зачем он столько токенов потратил на релизацию методов Array и String — это вопрос... Впрочем, это новый уровень «домашних работ» в 2026 году.

byko3y ★★★★
()

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

anonymous_sama ★★★★★
()
Ответ на: комментарий от anonymous_sama

Но конечно такого человека интересно было бы в штате иметь среди разработчиков.

«Такого» — это какого? Сейчас кодерские конторы воют, потому что все джуны поголовно вайбкодят и перегружают сеньоров ревью вот такого говнокода. Джун тратит 5 минут на генерацию коммита на 500 строк — сеньор тратит час на его ревью. Я уже имел честь с такими работать.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

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

И, да, сейчас массово загоняют людей обратно в офисы — именно так, как ты пишешь, «изобрази рабочий процесс, чтобы было видно, что ты там не чилишь в баре, пока твой агент пишет код».

byko3y ★★★★
()
Ответ на: комментарий от Beewek

Скромно оставил за скобками незначительные аспекты своего проекта. Да, есть теория, что статья на английском тоже нейросетью написана.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

anonymous_sama ★★★★★
()
Ответ на: комментарий от anonymous_sama

соответственно может в теории найти узкие места в процессах или рассказать как что-то работает намного глубже обычного сеньера.

Нет, лол. Дать ИИ команду «ну сделать там чота, ну типа как в ноде оно оптимизирововано» — это не «в теории найти узкие места в процессах».

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

anonymous_sama ★★★★★
()
Последнее исправление: anonymous_sama (всего исправлений: 1)
Ответ на: комментарий от anonymous_sama

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

«Звучит как будто убил медведя» — это не то же самое, что убить медведя. Что слишком много в интернете всего разного последние годы «звучит» — это правда.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Вообще-то это по нынешним временам довольно необычно. Сейчас все наоборот, хвастаются тем, что им помогал ии. Может всё же сам?

Beewek ★★★
()
Ответ на: комментарий от Beewek

Может я что-то не понимаю в жизни людей в 2026, но я чот не вижу людей, бегающих с криками: «смотрите, какой у меня классное резюме, написанное нейросетью! А ещё на собеседовании я такую хорошую неросеть применяю! И кодить я не умею — да и зачем, если нейросеть напишет лучше?». Ну то есть на линкедине и реддите такие посты есть, но эти же люди не пишут в резюме об этом прямо — факт применения ИИ очень часто скрывается и замалчивается в ключевых моментах.

Есть люди, которые идут на интеграторов ИИ — они тоже могут говорить о том, как классно умеют применять ИИ, но частенько забывают уточнить, что это ИИ применяют не они, а Aider, которым они задают промт «сделай мне репозиторий с проетом на питоне, который генерирует картинки по записям из БД и по расписанию отправляет сообщения с картинками в группы в телеграмме». Опять же, здесь если заказчик не полный лопух, то он спросит «а вот если у вас что-то сломалось, или информация нестандартная — вы что делать будете?» — в этом моменте эксперты по ИИ могут очень внезапно закончиться. А ведь именно в проблемных местах и нужен эксперт — шаблонную штуку можно набросать в Zapier, для этого «иксперт» не нужен.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Скромно оставил за скобками незначительные аспекты своего проекта. Да, есть теория, что статья на английском тоже нейросетью написана.

Ну тогда все честно, ИИ агент написал код, потом написал статью как он это сделал)

Честно говоря не верится, что такое можно сделать за месяц самому, без ИИ.

goingUp ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.