du + команда дерева (без установки дерева)

Поиск в Google иack-завершен! У меня есть ответ.

Но сначала позвольте мне еще немного пояснить цель вопроса :Я хочу четко различать независимые процессы в системе и счетчики их производительности. Например, ядро ​​процессора, неядерное устройство (узнало об этом недавно ), ядро ​​или пользовательское приложение на процессоре, шина (= контроллер шины ), жесткий диск — все это независимые процессы, они не синхронизированы по часам. И в настоящее время, наверное, у всех есть какой-нибудь счетчик мониторинга процессов (PMC ). Я хотел бы понять, из каких процессов берутся счетчики. (Также полезно гуглить :«поставщик» вещи, лучше обнуляет ее.)

Также шестерня используется для поиска :Ubuntu 14.04, linux 3.13.0-103-generic, процессорIntel(R) Core(TM) i5-3317U CPU @ 1.70GHz(от /proc/cpuinfo, имеет 2 физических ядра и 4 виртуальных --физической материи здесь ).

Терминология, вопросы, связанные с вопросом

От Intel:

  • процессор - это coreустройство (это 1 устройство/процесс )и куча uncoreустройств , coreэто то, что запускает программу (часы, АЛУ, регистры и т. д. ), uncore— это устройства, помещенные на кристалл, близкие к процессору по скорости и малой задержке (настоящая причина — «потому что производитель может это сделать» );как я понял это в основном северный мост, как на материнской плате ПК, плюс кэши; и AMD на самом деле называет эти устройства NorthBridge instead ofuncore `;

  • ubox, который появляется в моемsysfs

    $ find /sys/devices/ -type d -name events 
    /sys/devices/cpu/events
    /sys/devices/uncore_cbox_0/events
    /sys/devices/uncore_cbox_1/events
    

    --— это uncoreустройство, которое управляет кэшем последнего уровня (LLC, последним перед попаданием в ОЗУ ); У меня 2 ядра, таким образом 2 LLC и 2 ubox;

  • Блок мониторинга процессора (PMU )— отдельное устройство, которое контролирует работу процессора и записывает их в счетчик мониторинга процессора (PMC)(подсчитывает промахи кэша, циклы процессора и т. д. ); они существуют на устройствах coreи uncore; доступ к coreосуществляется с помощью инструкцииrdpmc(read PMC ); доступ к uncore, поскольку эти устройства зависят от фактического имеющегося процессора, осуществляется через специальные регистры модели (MSR )через rdmsr(, естественно );

    судя по всему, рабочий процесс с ними осуществляется через пары регистров --1 регистр задает какие события считает счетчик, 2 регистр это значение в счетчике; счетчик можно настроить на увеличение после кучи событий, а не только на 1; + есть некоторые прерывания/технические заметки о переполнении этих счетчиков;

  • больше можно найти в Intel "IA -32 Software Developer's Manual Vol 3B" глава 18 "МОНИТОРИНГ ПРОИЗВОДИТЕЛЬНОСТИ";

    так же формат MSR конкретно для этих uncorePMC для версии "Architectural Performance Monitoring Version 1" (в мануале есть версии 1 -4, не знаю какой у меня процессор)описан в «Рис. 18 -1. Компоновка IA32 _PERFEVTSELx MSR» (, стр. 18 -3 в шахте ), и в разделе «18.2.1.2 Предварительно -определенные архитектурные характеристики События» с помощью «Таблица 18 -1. UMask и кодирование выбора событий для событий предварительной -определенной архитектурной производительности», в которой показаны события, отображаемые как Hardware eventв perf list.

Из ядра Linux:

  • ядро ​​имеет систему (абстракцию/уровень )для управления счетчиками производительности различного происхождения, как программными (ядра ), так и аппаратными, это описано в linux-source-3.13.0/tools/perf/design.txt; событие в этой системе определяется какstruct perf_event_attr(файл linux-source-3.13.0/include/uapi/linux/perf_event.h), основная часть которого, вероятно, __u64 configполе --оно может содержать как определение события, специфичное для ЦП -(, так и 64-битное слово в формат, описанный в этих рисунках Intel )или в событии ядра

    The MSB of the config word signifies if the rest contains [raw CPU's or kernel's event]

    событие ядра определяется 7 битами для типа и 56 для идентификатора события, которые в коде равныenum-s, в моем случае это:

    $ ak PERF_TYPE linux-source-3.13.0/include/
    ...
    linux-source-3.13.0/include/uapi/linux/perf_event.h
    29: PERF_TYPE_HARDWARE      = 0,
    30: PERF_TYPE_SOFTWARE      = 1,
    31: PERF_TYPE_TRACEPOINT    = 2,
    32: PERF_TYPE_HW_CACHE      = 3,
    33: PERF_TYPE_RAW           = 4,
    34: PERF_TYPE_BREAKPOINT    = 5,
    36: PERF_TYPE_MAX,         /* non-ABI */
    

    (ak— это мой псевдоним для ack-grep, который является названием ackв Debian; и ackпотрясающе );

    в исходном коде ядра можно увидеть такие операции, как «регистрация всех PMU, обнаруженных в системе» и типы структур struct pmu, которые передаются чему-то вроде int perf_pmu_register(struct pmu *pmu, const char *name, int type)--, таким образом, эту систему можно было бы просто назвать «PMU ядра». ", который будет представлять собой совокупность всех PMU в системе; но это название может быть истолковано как система мониторинга операций ядра, что может ввести в заблуждение;

    назовем эту подсистему perf_eventsдля ясности;

  • как и любая подсистема ядра, эта подсистема может быть экспортирована в sysfs(, который предназначен для экспорта подсистем ядра для использования людьми ); и что это за eventsкаталоги в моих/sys/--экспортированных (частях?)perf_eventsподсистема;

  • кроме того, пользовательская -космическая утилита perf(, встроенная в linux ), по-прежнему является отдельной программой и имеет свои собственные абстракции; он представляет событие, запрошенное пользователем для мониторинга, в видеperf_evsel(файловlinux-source-3.13.0/tools/perf/util/evsel.{h,c})--эта структура имеет поле struct perf_event_attr attr;, а также поле типа struct cpu_map *cpus;, так perfутилита назначает событие всем или отдельным процессорам.

Ответ

  1. Действительно,Hardware cache event— это «ярлыки» к событиям кэш-устройств(uboxустройств Intel uncore), которые зависят от процессора -и могут быть доступны через протокол Raw hardware event descriptor. И Hardware eventболее стабильны в рамках архитектуры, которая, как я понимаю, именует события от coreустройства. В моем ядре нет других «ярлыков» 3.13для некоторых других uncoreсобытий и счетчиков. Все остальные--SoftwareиTracepoints--— это события ядра.

    Интересно, доступ к coreи Hardware eventосуществляется через один и тот же протокол Raw hardware event descriptor. Они могут не --, так как счетчик/PMU находится на core, возможно, доступ к ним осуществляется по-другому. Например, с этой инструкцией rdpmuвместо rdmsr, которая обращается к uncore. Но это не так важно.

  2. Kernel PMU event— это просто события, которые экспортируются в sysfs. Я не знаю, как это делается (автоматически ядром для всех обнаруженных PMC в системе, или просто что-то жестко -закодировано, и если я добавлю kprobe--, экспортируется ли он? и т. д. ). Но главное, что это такие же события, как Hardware eventили любые другие во внутренней perf_eventсистеме.

    А я не знаю, что это за

    $ ls /sys/devices/uncore_cbox_0/events
    clockticks
    

    ар.

Подробнее оKernel PMU event

Поиск по коду приводит к:

$ ak "Kernel PMU" linux-source-3.13.0/tools/perf/
linux-source-3.13.0/tools/perf/util/pmu.c                                                            
629:                printf("  %-50s [Kernel PMU event]\n", aliases[j]);

--что происходит в функции

void print_pmu_events(const char *event_glob, bool name_only) {
  ...
        while ((pmu = perf_pmu__scan(pmu)) != NULL)
                list_for_each_entry(alias, &pmu->aliases, list) {...}
  ... 
   /* b.t.w. list_for_each_entry is an iterator
    * apparently, it takes a block of {code} and runs over some lost
    * Ruby built in kernel!
    */
    // then there is a loop over these aliases and
    loop{... printf("  %-50s [Kernel PMU event]\n", aliases[j]);... }
}

и perf_pmu__scanнаходятся в одном файле:

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
   ...
                pmu_read_sysfs(); // that's what it calls
}

--который также находится в том же файле:

/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}

Вот именно.

Подробная информация о Hardware eventиHardware cache event

Судя по всему, Hardware eventпроисходят из того, что Intel называет «Предварительно -определенными событиями производительности архитектуры», 18.2.1.2 в IA -32 Руководство разработчика программного обеспечения, том 3B. И «18.1 ОБЗОР МОНИТОРИНГА ПРОИЗВОДИТЕЛЬНОСТИ» руководства описывает их как:

The second class of performance monitoring capabilities is referred to as architectural performance monitoring. This class supports the same counting and Interrupt-based event sampling usages, with a smaller set of available events. The visible behavior of architectural performance events is consistent across processor implementations. Availability of architectural performance monitoring capabilities is enumerated using the CPUID.0AH. These events are discussed in Section 18.2.

--другой тип:

Starting with Intel Core Solo and Intel Core Duo processors, there are two classes of performance monitoring capa-bilities. The first class supports events for monitoring performance using counting or interrupt-based event sampling usage. These events are non-architectural and vary from one processor model to another...

И эти события действительно являются просто ссылками на базовые «сырые» аппаратные события, доступ к которым можно получить с помощью утилиты perfкак Raw hardware event descriptor.

Чтобы проверить это, посмотрите наlinux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c:

/*
 * Intel PerfMon, used on Core and later.
 */
static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
{
    [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
    [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
    [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
    [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
   ...
}

--и точно 0x412eможно найти в «Таблице 18 -1. UMask и кодировки выбора событий для предварительно -определенных событий архитектурной производительности» для «промахов LLC»:

Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
                        4 | LLC Misses | 41H   | 2EH

--Hдля шестнадцатеричных. В структуре есть все 7, плюс [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *. (Именование немного другое, адреса те же.)

Тогда Hardware cache eventнаходятся в структурах типа (в том же файле):

static __initconst const u64 snb_hw_cache_extra_regs
                            [PERF_COUNT_HW_CACHE_MAX]
                            [PERF_COUNT_HW_CACHE_OP_MAX]
                            [PERF_COUNT_HW_CACHE_RESULT_MAX] =
{...}

--какой должен быть песчаный мост?

Один из них--snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]заполнен SNB_DMND_WRITE|SNB_L3_ACCESS, где из определения -выше:

#define SNB_L3_ACCESS           SNB_RESP_ANY
#define SNB_RESP_ANY            (1ULL << 16)                                                                            
#define SNB_DMND_WRITE          (SNB_DMND_RFO|SNB_LLC_RFO)
#define SNB_DMND_RFO            (1ULL << 1)
#define SNB_LLC_RFO             (1ULL << 8)

, что должно равняться 0x00010102, но я не знаю, как это проверить с помощью какой-то таблицы.

И это дает представление о том, как оно используется вperf_events:

$ ak hw_cache_extra_regs linux-source-3.13.0/arch/x86/kernel/cpu/
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.c
50:u64 __read_mostly hw_cache_extra_regs
292:    attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];

linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.h
521:extern u64 __read_mostly hw_cache_extra_regs

linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
272:static __initconst const u64 snb_hw_cache_extra_regs
567:static __initconst const u64 nehalem_hw_cache_extra_regs
915:static __initconst const u64 slm_hw_cache_extra_regs
2364:       memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2365:              sizeof(hw_cache_extra_regs));
2407:       memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
2408:              sizeof(hw_cache_extra_regs));
2424:       memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2425:              sizeof(hw_cache_extra_regs));
2452:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2453:              sizeof(hw_cache_extra_regs));
2483:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2484:              sizeof(hw_cache_extra_regs));
2516:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
$

memcpyвыполняются в __init int intel_pmu_init(void) {... case:...}.

Только attr->config1немного странно. Но он есть, вperf_event_attr(том же linux-source-3.13.0/include/uapi/linux/perf_event.hфайле):

...
    union {
            __u64           bp_addr;
            __u64           config1; /* extension of config */                                                      
    };
    union {
            __u64           bp_len;
            __u64           config2; /* extension of config1 */
    };
...

Они зарегистрированы в системе ядра perf_eventsс вызовами int perf_pmu_register(struct pmu *pmu, const char *name, int type)(, определенными в linux-source-3.13.0/kernel/events/core.c:):

.

  • static int __init init_hw_perf_events(void)(файлarch/x86/kernel/cpu/perf_event.c)с вызовомperf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);

  • static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)(файл arch/x86/kernel/cpu/perf_event_intel_uncore.c, есть ещеarch/x86/kernel/cpu/perf_event_amd_uncore.c)с вызовомret = perf_pmu_register(&pmu->pmu, pmu->name, -1);

Итак, наконец, все события исходят от оборудования, и все в порядке. Но тут можно было заметить :, почему у нас LLC-loadsв perf list, а не ubox1 LLC-loads, ведь это HW-события и они на самом деле исходят из uboxes?

Это особенность утилиты perfи ее perf_evselструктуры :, когда вы запрашиваете событие HW от perfвы определяете событие, от каких процессоров вы хотите получить его (по умолчанию все ), и устанавливает perf_evselс запрошенным событием и процессорами, затем при агрегации суммирует счетчики со всех процессоров вperf_evsel(или делает с ними какую-то другую статистику ).

Это можно увидеть вtools/perf/builtin-stat.c:

/*
 * Read out the results of a single counter:
 * aggregate counts across CPUs in system-wide mode
 */
static int read_counter_aggr(struct perf_evsel *counter)
{
    struct perf_stat *ps = counter->priv;
    u64 *count = counter->counts->aggr.values;
    int i;

    if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
                           thread_map__nr(evsel_list->threads), scale) < 0)
            return -1;

    for (i = 0; i < 3; i++)
            update_stats(&ps->res_stats[i], count[i]);

    if (verbose) {
            fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
                    perf_evsel__name(counter), count[0], count[1], count[2]);
    }

    /*
     * Save the full runtime - to allow normalization during printout:
     */
    update_shadow_stats(counter, count);

    return 0;
}

(Итак, для утилиты perf"один счетчик" - это даже не perf_event_attr, что является общей формой, подходящей как для программных, так и для аппаратных событий,это событие вашего запроса --одни и те же события могут поступать с разных устройств и они агрегируются.)

Также уведомление:struct perf_evselсодержит только 1 struct perf_evevent_attr, но оно также имеет поле struct perf_evsel *leader;--, оно вложенное. Есть фича "(иерархических )групп событий" в perf_events, когда можно рассылать кучу счетчиков вместе, чтобы их можно было сравнивать друг с другом и так далее. Не уверен, как это работает с независимыми событиями из kernel, core, ubox. Но это вложение perf_evsel. И, скорее всего, именно так perfсправляется с запросом нескольких событий вместе.

2
12.09.2019, 16:06
1 ответ

Я думаю, вам следует поменять порядок du -hна tac, а затем применить форматирование к sed. Это должно работать для «обычных» имен каталогов (без управляющих символов ):

.
du -h | tac | sed 's_[^/[:cntrl:]]*/_--_g;s/-/|/'

Или используйтеfind -exec:

find. -type d -exec du -sm {} \; | sed 's_[^/[:cntrl:]]*/_--_g;s/-/|/'
0
27.01.2020, 22:24

Теги

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