В каком сценарии полезно использовать дизассемблирование на python? - PullRequest
3 голосов
/ 20 апреля 2010

Модуль dis можно эффективно использовать для разборки методов, функций и классов Python в низкоуровневые инструкции интерпретатора.

Я знаю, что dis информация может использоваться для:
1. Найти расуусловия в программах, использующих потоки
2. Найти возможные оптимизации

Из своего опыта знаете ли вы какие-либо другие сценарии, в которых функция дизассемблирования Python могла бы быть полезной?

Ответы [ 3 ]

7 голосов
/ 20 апреля 2010

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

Пример: list += [item] против list.append(item)

def f(x): return 2*x

def f1(func, nums):
  result = []
  for item in nums:
    result += [fun(item)]
  return result

def f2(func, nums):                       
  result = []
  for item in nums:
    result.append(fun(item))
  return result

timeit.timeit говорит, что f2(f, range(100)) примерно в два раза быстрее, чем f1(f, range(100). Почему?

(Интересно, что f2 примерно такой же быстрый, как map(f, range(100)).)

f1

Вы можете увидеть весь вывод dis, вызвав dis.dis(f1), вот строка 4.

  4          19 LOAD_FAST                2 (result)
             22 LOAD_FAST                1 (fun)
             25 LOAD_FAST                3 (item)
             28 CALL_FUNCTION            1 
             31 BUILD_LIST               1 
             34 INPLACE_ADD                
             35 STORE_FAST               2 (result) 
             38 JUMP_ABSOLUTE           13 
        >>   41 POP_BLOCK           

f2

Опять же, здесь только строка 4:

  4          19 LOAD_FAST                2 (result)
             22 LOAD_ATTR                0 (append)
             25 LOAD_FAST                1 (fun)
             28 LOAD_FAST                3 (item)
             31 CALL_FUNCTION            1 
             34 CALL_FUNCTION            1 
             37 POP_TOP                    
             38 JUMP_ABSOLUTE           13 
        >>   41 POP_BLOCK           

Найди разницу

В f1 нам нужно:

  • Звоните fun на item (код операции 28)
  • Составьте из него список (код операции 31, дорого!)
  • Добавить к result (код операции 34)
  • Сохранить возвращаемое значение в result (код операции 35)

В f2 вместо этого мы просто:

  • Звоните fun на item (код операции 31)
  • Звоните append на result (код операции 34; код C: быстро!)

Это объясняет, почему (imho) более выразительный list += [value] намного медленнее, чем list.append() метод.


Кроме этого, dis.dis в основном полезен для любопытства и для попытки восстановить код из .pyc файлов, у которых нет источника, не потратив целое состояние:)

5 голосов
/ 20 апреля 2010

Я вижу модуль dis как инструмент обучения. Понимание того, что кодирует определенный фрагмент кода Python, является началом более глубокого понимания Python - внедрения «абстрактного» понимания его семантики в образец (чуть больше) конкретной реализации. Иногда точную причину, по которой определенный фрагмент кода Python ведет себя так, как он это делает, может быть трудно понять «сверху вниз», исходя из «правил» семантики Python: в таких случаях подкрепление исследования некоторой проверкой «снизу вверх» (конечно, на основе возможной реализации - возможны и другие реализации ;-) может реально помочь эффективности исследования.

3 голосов
/ 20 апреля 2010

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

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

>>> def f():
...     def foo(x=[1, 2, 3]):
...         y = [4,]
...         return x + y
... 
>>> dis(f)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 LOAD_CONST               4 (<code object foo at 0xb7690770, file "<stdin>", line 2>)
             15 MAKE_FUNCTION            1
             18 STORE_FAST               0 (foo)
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        

Вы можете увидеть, что это происходит, помещая константы 1, 2 и 3 в стек, помещая содержимое стека в список, загружая его в объект кода, превращая функцию кода в объект и сохраняя ее. в переменную foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...