Skip to the content.

QEMU 中的 trace 机制

关键参考

https://github.com/qemu/qemu/blob/master/docs/devel/tracing.rst 这就是全部内容了

qemu 的 trace 默认 backend 是可以动态添加 trace 的

发现即便是 backend 是 nop ,还是有如下的内容:

(qemu) info trace-events
handle_qmp_command : state 0
monitor_qmp_respond : state 0
monitor_qmp_cmd_out_of_band : state 0
monitor_qmp_err_in_band : state 0
monitor_qmp_cmd_in_band : state 0
monitor_qmp_in_band_dequeue : state 0
monitor_qmp_in_band_enqueue : state 0
monitor_suspend : state 0
monitor_protocol_event_queue : state 0
monitor_protocol_event_emit : state 0
monitor_protocol_event_handler : state 0
handle_hmp_command : state 0

相关文件

这个脚本 scripts/qemu-trace-stap 这个目录 : trace/

各种配置的展开

  --enable-trace-backends=CHOICES
                           Set available tracing backends [log] (choices:
                           dtrace/ftrace/log/nop/simple/syslog/ust)

默认配置

默认配置不会导致性能下降?

/home/martins3/core/qemu/build/trace/trace-softmmu.h

static inline void _nocheck__trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    if (trace_event_get_state(TRACE_MEMORY_REGION_OPS_READ) && qemu_loglevel_mask(LOG_TRACE)) {
        if (message_with_timestamp) {
            struct timeval _now;
            gettimeofday(&_now, NULL);
#line 12 "/home/martins3/core/qemu/softmmu/trace-events"
            qemu_log("%d@%zu.%06zu:memory_region_ops_read " "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u name '%s'" "\n",
                     qemu_get_thread_id(),
                     (size_t)_now.tv_sec, (size_t)_now.tv_usec
                     , cpu_index, mr, addr, value, size, name);
#line 199 "trace/trace-softmmu.h"
        } else {
#line 12 "/home/martins3/core/qemu/softmmu/trace-events"
            qemu_log("memory_region_ops_read " "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u name '%s'" "\n", cpu_index, mr, addr, value, size, name);
#line 203 "trace/trace-softmmu.h"
        }
    }
}

–enable-trace-backends=simple


static inline void _nocheck__trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    _simple_trace_memory_region_ops_read(cpu_index, mr, addr, value, size, name);
}

void _simple_trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    TraceBufferRecord rec;
    size_t argname_len = name ? MIN(strlen(name), MAX_TRACE_STRLEN) : 0;

    if (!trace_event_get_state(TRACE_MEMORY_REGION_OPS_READ)) {
        return;
    }

    if (trace_record_start(&rec, _TRACE_MEMORY_REGION_OPS_READ_EVENT.id, 8 + 8 + 8 + 8 + 8 + 4 + argname_len)) {
        return; /* Trace Buffer Full, Event Dropped ! */
    }
    trace_record_write_u64(&rec, (uint64_t)cpu_index);
    trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)mr);
    trace_record_write_u64(&rec, (uint64_t)addr);
    trace_record_write_u64(&rec, (uint64_t)value);
    trace_record_write_u64(&rec, (uint64_t)size);
    trace_record_write_str(&rec, name, argname_len);
    trace_record_finish(&rec);
}

–enable-trace-backends=simple,ftrace

如果配置了两个日志,那么日志就会写入到两个地方中去:

static inline void _nocheck__trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    _simple_trace_memory_region_ops_read(cpu_index, mr, addr, value, size, name);
    {
        char ftrace_buf[MAX_TRACE_STRLEN];
        int unused __attribute__ ((unused));
        int trlen;
        if (trace_event_get_state(TRACE_MEMORY_REGION_OPS_READ)) {
#line 12 "/home/martins3/core/qemu/softmmu/trace-events"
            trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,
                             "memory_region_ops_read " "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u name '%s'" "\n" , cpu_index, mr, addr, value, size, name);
#line 223 "trace/trace-softmmu.h"
            trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);
            unused = write(trace_marker_fd, ftrace_buf, trlen);
        }
    }
}

–enable-trace-backends=ftrace

似乎真的就是 ftrace 只是作用于 ftrace 了:

static inline void _nocheck__trace_memory_region_ops_write(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    {
        char ftrace_buf[MAX_TRACE_STRLEN];
        int unused __attribute__ ((unused));
        int trlen;
        if (trace_event_get_state(TRACE_MEMORY_REGION_OPS_WRITE)) {
#line 20 "../system/trace-events"
            trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,
                             "memory_region_ops_write " "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u name '%s'" "\n" , cpu_index, mr, addr, value, size, name);
#line 386 "trace/trace-system.h"
            trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);
            unused = write(trace_marker_fd, ftrace_buf, trlen);
        }
    }
}

–enable-trace-backends=nop

static inline void _nocheck__trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
}

–enable-trace-backends=ust

似乎这个就是我想要的,没有任何性能损失的

static inline void _nocheck__trace_memory_region_ops_read(int cpu_index, void * mr, uint64_t addr, uint64_t value, unsigned size, const char * name)
{
    tracepoint(qemu, memory_region_ops_read, cpu_index, mr, addr, value, size, name);
}

dtrace 还没有测试过

使用 ftrace 的时候,是不是实际上将信息导入到 kernel 的 ftrace buffer 中?

qemu-system-x86_64 -trace help

测试一下,如果添加 trace 对于性能的影响有多少?

使用 fio 4k randread virtio-blk 来测试 875k 894k

大约 2% 的性能差别,其实勉强可以接受吧

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。