Что является самым быстрым (к доступу) подобный структуре объект в Python?

Следующий код позволяет вам получить весь стекTrace с форматом String без использования API, таких как log4J или даже java.util.Logger:

catch (Exception e) {
    StackTraceElement[] stack = e.getStackTrace();
    String exception = "";
    for (StackTraceElement s : stack) {
        exception = exception + s.toString() + "\n\t\t";
    }
    System.out.println(exception);
    // then you can send the exception string to a external file.
}
75
задан DNS 15 April 2010 в 14:29
поделиться

5 ответов

Следует иметь в виду, что именованные кортежи оптимизированы для доступа как кортежи. Если вы измените свой метод доступа на a [2] вместо a.c , вы увидите производительность, аналогичную кортежам. Причина в том, что средства доступа к имени эффективно преобразуются в вызовы self [idx], поэтому заплатите как индексирование , так и цену поиска имени.

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

def makestruct(name, fields):
    fields = fields.split()
    import textwrap
    template = textwrap.dedent("""\
    class {name}(object):
        __slots__ = {fields!r}
        def __init__(self, {args}):
            {self_fields} = {args}
        def __getitem__(self, idx): 
            return getattr(self, fields[idx])
    """).format(
        name=name,
        fields=fields,
        args=','.join(fields), 
        self_fields=','.join('self.' + f for f in fields))
    d = {'fields': fields}
    exec template in d
    return d[name]

Но время очень плохое, когда необходимо вызвать __ getitem __ :

namedtuple.a  :  0.473686933517 
namedtuple[0] :  0.180409193039
struct.a      :  0.180846214294
struct[0]     :  1.32191514969

то есть такая же производительность, как у класса __ slots __ для доступа к атрибутам (неудивительно - вот что это такое), но огромные штрафы из-за двойного поиска при доступе на основе индекса. (Следует отметить, что __ slots __ на самом деле не очень помогает с точки зрения скорости. Это экономит память, но время доступа примерно такое же без них.)

Третьим вариантом было бы дублирование данных, например. подкласс из списка и сохраните значения как в атрибутах, так и в данных списка. Однако на самом деле вы не получаете производительности, эквивалентной списку. Большой удар по скорости достигается только при наличии подклассов (включая проверки на наличие перегрузок на чистом питоне). Таким образом, struct [0] по-прежнему занимает около 0,5 с (по сравнению с 0,18 для необработанного списка) в этом случае, и вы удваиваете использование памяти, так что это может не окупаться.

50
ответ дан 24 November 2019 в 11:42
поделиться

Эта проблема может скоро быть устаревшей. CPython dev очевидно сделал существенные улучшения к выполнению доступа к именованным значениям кортежа названием атрибута. Изменения запланированы к выпуску в Python 3.8 около конца октября 2019.

См.: https://bugs.python.org/issue32492 и https://github.com/python/cpython/pull/10495.

1
ответ дан 24 November 2019 в 11:42
поделиться

Пара моментов и идей:

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

2) OrderedDictionary написан как оболочка вокруг dict , следовательно, он будет медленнее, чем dict . Это не решение.

3) Вы пробовали уроки как нового, так и старого стиля? (классы нового стиля наследуются от объекта ; классы старого стиля - нет)

4) Пробовали ли вы использовать psyco или Unladen Swallow ?

] 5) Изменяет ли ваш внутренний цикл данные или просто обращается к ним? Можно было бы преобразовать данные в наиболее эффективную форму перед входом в цикл, но используйте наиболее удобную форму в другом месте программы.

3
ответ дан 24 November 2019 в 11:42
поделиться

У меня возникнет соблазн: (а) изобрести какое-то кэширование для конкретных рабочих нагрузок и переложить хранение и извлечение моих данных на процесс, подобный memcachedb , чтобы улучшить масштабируемость, а не только производительность, или (б) переписать как расширение C с собственным хранилищем данных. Возможно, тип упорядоченного словаря.

Вы можете начать с этого: http://www.xs4all.nl/~anthon/Python/ordereddict/

1
ответ дан 24 November 2019 в 11:42
поделиться

Вы можете сделать свои классы последовательными, например, добавив методы __ iter __ и __ getitem __ , чтобы сделать их последовательными, как (индексируемый и повторяемый.)

Будет ли работать OrderedDict ? Доступно несколько реализаций, и он включен в модуль Python31 collections .

-1
ответ дан 24 November 2019 в 11:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: