Рубрика «jit» - 6

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

Ранее мы познакомились с языком Smalltalk, а точнее с его микро реализацией Little Smalltalk. Разобрались с синтаксисом языка, форматом представления объектов в памяти и набором основных инструкций. Теперь мы вплотную подошли к вопросам взаимодействия Smalltalk и LLVM (ради этого и затевалась вся серия статей).

Сейчас у нас есть вся необходимая база знаний для того чтобы понять, что именно делается в нашем JIT компиляторе. В этой статье мы узнаем, как байт-коды Smalltalk преобразуются в IR код LLVM, как происходит компиляция и выполнение кода, и почему это работает быстрее, чем программная интерпретация. Самые нетерпеливые могут посмотреть шеллкасты (раз и два), с циферками и бегущими строчками (не забывайте про возможность скроллинга).
Читать полностью »

Мир движется к 64-битным вычислениям, несмотря на то, что в результате программы не всегда работают быстрее или производительнее по сравнению с 32-битными. Многие 32-битные программы, по разным причинам, могут работать быстрее 64-битных. Одним из таких примеров является 64-битный JIT-компилятор .NET-фреймворка. Он выполняет большую работу для того, чтобы ваша программа работала очень быстро, но сам он, увы, не настолько быстр, как хотелось бы. Это мы и собираемся исправить. Представляем x64 JIT-компилятор нового поколения, который способен компилировать 64-битный .NET код в 2 раза быстрее.
Читать полностью »

Около двенадцати часов назад Джон Резиг нащебетал в Твиттер, что на конференции Google I/O было объявлено о поддержке Asm.js в движке V8 и во браузере Google Chrome.

Так как про Asm.js упоминали на Хабрахабре (1, 2), то достоинства его могли стать известны многим читателям. Тем приятнее им предвкушать теперь в самом скором времени появление этих достоинств не только во браузере Firefox (где они впервые были внедрены Фондом Мозиллы), но и в движке V8 (а значит — в построенном на его основе движке Node.js!), и во браузере Google Chrome.

Но для тех читателей, которые до сих пор пропускали эту новинку мимо себя, я также вкратце напомню суть. Asm.js — это особое подмножество языка JavaScript: ограничившись им в своём скрипте, автор скрипта обеспечивает возможность оптимизации интерпретируемого кода не только в момент исполнения (just-in-time, JIT), но даже и заблаговременно (ahead-of-time, AOT), то есть такому джаваскрипту становится возможно один раз однозначно заранее поставить в соответствие некоторый машинный код. Эффект этот достигается ценою заметных усилий по самоограничению. (В частности, при помощи операции «|0» и других специальных приёмов тип значения каждого входного параментра функции, равно как и выходного значения, оказывается однозначно заданным и неизменным.) Зато его итогом становится небывалый рост скорости исполнения джаваскрипта — теперь по скорости он уступает скомпилированной программе (на Си или Си++) не более чем в два раза.

Читать полностью »

Да, это целая статья по самому обычному switch в JDK 7. Бывает так, что накопленный материал кажется интересным и малоизвестным, а потом оказывается, что любая бабка у подъезда уже 50 лет знает об особенностях реализации switch. Но я попробую. Для затравки, предлагаю 3 вопроса:

  1. (Простой) Каков результат работы этого кода?
    switch(5){
    default: System.out.print(0);
    case 1: System.out.print(1); break;
    case 4: System.out.print(4);
    case 2: System.out.print(2);
    }

  2. Следующие 2 варианта практически одинаковы. Немного отличаются литералами.
    //Вариант 1
    switch("BBBBBB"){
    case "AaAaAa": break; 
    case "AaAaBB": break;
    case "AaBBAa": break;
    case "AaBBBB": break;
    case "BBAaAa": break;
    case "BBAaBB": break;
    case "BBBBAa": break;
    case "BBBBBB": break;
    }
    //Вариант 2
    switch("BBBBBB_8"){
    case "AaAaAa_1": break;
    case "AaAaBB_2": break;
    case "AaBBAa_3": break;
    case "AaBBBB_4": break;
    case "BBAaAa_5": break;
    case "BBAaBB_6": break;
    case "BBBBAa_7": break;
    case "BBBBBB_8": break;
    }

    Почему первый switch выполняется в несколько раз медленнее, по крайней мере, с отключенным JIT (-Djava.compiler=NONE)? Сами проверьте в цикле! JIT таким кодом не проведешь, но если немного пошаманить, то небольшая разница будет заметна.

  3. Какова вычислительная сложность алгоритма нахождения совпадающего значения среди n case-ов (по крайней мере, в JDK 7)?

Читать полностью »

asm.js — новый язык?

Нет, это просто подмножество JavaScript. Программа на asm.js одинаково поведёт себя и в существующих движках JavaScript, и в движке с предварительной (ahead-of-time, AOT) компиляцией, способном распознавать и оптимизировать asm.js; различаться будет её скорость, разумеется!

Какой выигрыш в производительности можно ожидать от asm.js?

Сейчас ещё рано утверждать. Однако наши предварительные измерения производительности программ, скомпилированных из Си в asm.js, показывают не более чем двукратное замедление по сравнению с компилированными в машинный код посредством clang. Мы опубликуем дальнейшие измерения, когда насобираем их.

Как я могу следить за ходом реализации?

Мозилла работает над первой реализацией оптимизирующего компилятора asm.js для SpiderMonkey. В вики Фонда Мозиллы также опубликован план разработки дальнейших выпусков и оптимизаций. Если авторы других движков JavaScript опубликуют собственные планы реализации компиляторов asm.js, мы их здесь упомянем.

Почему бы вам не разработать синтаксис байткода вместо необычного диалекта джаваскрипта?

Для компиляторов наподобие Emscripten или Mandreel синтаксис байткодового языка попросту не особенно значим. Притом большинство байткодов и вообще машинных языков имеют двоичный формат, не читаемый людьми. Однако мы можем создать на уровне asm.js более человеко-читаемый синтаксис, который будет и удобным в дизассемблировании, и пригодным для чтения и записи людьми.

То обстоятельство, что asm.js — это JavaScript, не обернётся ли непредсказуемым выполнением кода?

Предварительная (ahead-of-time, AOT) компиляция asm.js может генерировать код, выполнение которого весьма предсказуемо, потому что валидный код asm.js ограничен крайне небольшим подмножеством JavaScript, состоящим только из строго типизированных целых чисел, чисел с плавающей точкою, арифметических операций, вызовов функций и обращения к куче.

Почему бы тогда не NaCl или PNaCl вместо этого? Вы просто упорствуете насчёт JavaScript?

Принципиальным достоинством asm.js по сравнению с новыми технологиями вроде NaCl и PNaCl является то, что asm.js работает сегодня: существующие движки JavaScript ужé неплохо оптимизируют код, написанный в таком стиле. Что означает, что разработчики могут выпускать код на asm.js сегодня, а со временем его работа будет ускоряться. Другою важною пользою является заметно бóльшая простота реализации, для которой потребуется совсем немного дополнительных механизмов поверх существующих движков JavaScript — и не понадобится слой совместимости API.

Читать полностью »

О компиляторах и интерпретаторах
Если ты всегда мечтал написать свой язык программирования — добро пожаловать. Здесь ты наверняка найдёшь для себя что-нибудь интересное.

GitHub-юзер yawnt собрал чудесную подборку ссылок для любителей драконов, языков и прочих вкусных внутренностей. А знающие камрады в комментариях наверняка поделятся с тобой и другими яствами.

Пишет yawnt следующее:

С каждым днём мне всё интереснее тема компиляторов, интерпретаторов и дизайна языков программирования в целом. И я решил поделиться с народом ссылками на собранные мной материалы (большую часть мне самому ещё предстоит прочитать :<). Надеюсь, кому-нибудь они окажутся полезными.

Я не включил (и не собираюсь) в список ссылки на официальную документацию, т. к. считаю очевидным, что первым делом следует смотреть именно туда ;P.
Читать полностью »

Многоядерная JIT компиляция в .NET 4.5
Исторически разработчики .NET использовали генератор образов в машинном коде Ngen. Это отлично работает, если у вас есть инсталлятор, и вы можете сгенерировать эти образы во время установки приложения. Но в других случаях, например когда у вас нет установщика или вы не имеете доступ к Ngen, ваше приложение будет производить JIT-компиляцию по мере необходимости, что замедлит его загрузку. Разработчики CLR предоставили решение в новой версии .NET – многоядерная JIT-компиляция с возможностью создавать профили оптимизации.
Читать полностью »

[цитата]Читатель, заходящий на сайт NodeJS.org, по центру страницы видит четыре цитаты от лидеров сайтостроения, выражающие удовольствие от Node. Цитаты меняются каждую минуту. При некотором везении (или терпении при перезагрузке страницы) читатель увидит похвалу от Клаудио Кальдато из Microsoft Open Technologies, Inc. — для вашего удобства я привожу эту цитату на иллюстрации справа.

Чем вызвана к жизни такая похвала? Ведь, казалось бы, задолго до того, как движок Node вообще успел появился на свет, у Microsoft существовало собственное (встроенное в Windows, начиная с Windows 98, а также устанавливаемое вместе с Internet Explorer 5) средство для запуска скриптов — Windows Script Host.

Ответ очевиден: Node.js работает гораздо быстрее. (У него, кстати, ещё и API попроще. Но главное — скорость.)

Но насколько именно быстрее Node, чем WSH?

Это нетрудно выяснить опытным путём. Возьмём тот скрипт, при помощи которого evgeniyup вчера сравнивал быстродействие WSH с быстродействием виртуальной машины своего языка ObjectScript. В начале скрипта добавим десяток строк — «костыль» для Node.js, реализующий WSH-функцию WScript.Echo при её отсутствии.

показать (или вновь скрыть) исходный код скрипта

// CScript to Node.js:
if (typeof WScript == "undefined") WScript = {};
if (typeof WScript.Echo == "undefined") WScript.Echo = function(){
  var i;
  var log = '';
  for (i=0; i < arguments.length; i++){
     log += arguments[i];
  }
  console.log(log);
}

var fannkuch = function(n)
{
  var p = [], q = [], s = [], sign = 1, maxflips = 0, sum = 0;
  var i;
  for(i=1; i<=n; i++) p[i] = q[i] = s[i] = i;
  for(;;){
    // Copy and flip.
    var q1 = p[1];				// Cache 1st element.
    if(q1 != 1){
      for(i=2; i<=n; i++) q[i] = p[i];		// Work on a copy.
      var flips = 1;
      for(;;){
        var qq = q[q1];
        if(qq == 1){				// ... until 1st element is 1.
          sum = sum + sign*flips;
          if(flips > maxflips){
            maxflips = flips;
          } // New maximum?
          break;
        }
        q[q1] = q1;
        if(q1 >= 4){
          var i = 2, j = q1 - 1
          for(;;){ var tmp = q[i]; q[i] = q[j]; q[j] = tmp; if(++i >= --j) break; }
        }
        q1 = qq; flips++;
      }
    }
    // Permute.
    if(sign == 1){
      var tmp = p[2]; p[2] = p[1]; p[1] = tmp; sign = -1;	// Rotate 1<-2.
    }else{
      var tmp = p[2]; p[2] = p[3]; p[3] = tmp; sign = 1;	// Rotate 1<-2 and 1<-2<-3.
      for(i = 3;; i++){
        // print "mark 4"
        var sx = s[i];
        if(sx != 1){ s[i] = sx-1; break; }
        if(i == n) return [sum, maxflips];	// Out of permutations.
        s[i] = i;
        // Rotate 1<-...<-i+1.
        var t = p[1]; for(var j = 1; j <= i; j++){ p[j] = p[j+1]; } p[i+1] = t;
      }
    }
  }
}

function getTimeSec(){
 	var d = new Date();
    return (d.getTime() + d.getMilliseconds() / 1000.0) / 1000.0;
}

var n = 10;
var start_time = getTimeSec();
var r = fannkuch(n);
var sum = r[0], flips = r[1];
WScript.Echo(
    sum,"n",
    "Pfannkuchen(",n,") = ",flips,"n",
    "time = ",(getTimeSec() - start_time),"n"
)

После этого достаточно запустить этот скрипт дважды (сперва в Node, затем в WSH) — и мы получим вот какой результат в консоли (и на скриншоте):

[скриншот]

Разница на два порядка! Вычисления, с которыми Node.js справляется за секунду, Windows Script Host перемалывал больше двух минут.

Читать полностью »

Alexandre Mutel — создатель самой быстрой и самой полной .NET обертки для DirectX, единственной, поддерживающей Windows 8 Metro, работает R&D разработчиком игрового движка в SiliconStudio, участник французской демо-группы FRequency.

В последнее время мы слышим много шума о возвращении идеи «Going Native» после эры управляемых языков, таких как Java и .NET. В прошлом году, когда WinRT был только представлен, начали появляться недалекие комментарии, которые утверждали, что что .NET умер, а С++ возвращается во всей своей красе — истинный и единственно верный способ для разработки приложений, в то время, как JIT начинает все чаще появляться в мире скриптовых языков (JavaScript активнее всех использует преимущества JIT). Любой код так или иначе станет нативным перед выполнением — разница лишь в длине пути, по которому он пройдет, чтобы стать нативным, и насколько оптимизированным он будет. Значение слова «native» немного изменилось и стало неразрывно связано со словом «производительность». Даже будучи сильным пропагандистом управляемого языка [C#], его производительность на самом деле ниже хорошо написанного С++ приложения. Получается, мы должны просто принять этот факт и вернуться к C++, когда такие штуки как WinRT будут для нас основой межязыкового взаимодействия? По правде говоря, я бы хотел, чтобы .NET умер, и этот пост о том, почему и зачем.
Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js