Подтвердить что ты не робот

Почему метод Ruby вызывает особенно медленный (по сравнению с другими языками)?

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

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

Может кто-нибудь объяснить более подробно, почему вызовы Ruby-метода особенно медленны и разрабатываются во втором потоке? Я не совсем уверен, что такое поздний поиск или почему он медленный, и я не знаю, какие имена для контекста означают или как он относится к вызовам фреймов и методов.

Мое (возможно, неверное) понимание состоит в том, что, поскольку методы могут быть добавлены или изменены во время выполнения, интерпретатор Ruby никогда не сможет "запомнить", как запустить конкретный метод, поэтому он должен искать этот метод каждый раз, когда программа запущена, и это означает, что вызовы методов медленны. Но исправления и более технические объяснения были бы замечательными.

4b9b3361

Ответ 1

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

Динамические языки, такие как Ruby, часто имеют медленную отправку методов, потому что вызывающий код имеет имя для метода, а не указатель (или индекс в массив, содержащий указатели). Вызывающий код должен запросить объект для своего класса, затем должен спросить класс, есть ли у него метод с этим именем, а если нет, перейдите в цепочку предков, спрашивающих каждого предка, если у него есть метод с таким именем ( это то, что делает компилятор на скомпилированном языке, поэтому компиляция выполняется медленно и отправка метода выполняется быстро). Вместо нескольких указаний на указатели, требующих всего нескольких машинных инструкций для вызова метода, динамический язык должен выполнять от десятков до сотен машинных инструкций для поиска класса объекта и всех классов-предков объекта для этого метода. Каждый класс имеет HashTable имен → методы, но HashTables со строковыми ключами на порядок медленнее, чем массивы с целыми индексами.

Есть способы оптимизировать отправку методов в динамических langauges, конечно. В Ruby работает то, над чем работают JRuby, Rubinius и IronRuby. Но это тема для другого вопроса.