Android质量测量检验工具,oprofile质量深入分析

By admin in 美高梅手机版4858 on 2019年7月21日

工欲善其事,必先利其器,oprofile是深入分析质量的利器。废话少说,直接上solution:

Oprofile解析(android oprofile品质深入分析),androidoprofile

一、内核扶助:
make menuconfig

1、评测菜单中启用 Oprofile ,在 .config
文件中安装?CONFIG_PROFILING=y?和?CONFIG_OPROFILE=y
2、Kernel Feature->[]Enable hardware performance counter support
for perf events不要勾选
3、在boot options->console=ttyFIQ0 androidboot.console=ttyFIQ0
init=/init profile=1
二、修改源码 将kernel/arch/arm/oprofile中的common.文件修改

/**                                
 * @file common.c                                
 *                                
 * @remark Copyright 2004 Oprofile Authors                                
 * @remark Copyright 2010 ARM Ltd.                                
 * @remark Read the file COPYING                                
 *                                
 * @author Zwane Mwaikambo                                
 * @author Will Deacon [move to perf]                                
 */                                

#include <linux/cpumask.h>                                
#include <linux/err.h>                                
#include <linux/errno.h>                                
#include <linux/init.h>                                
#include <linux/mutex.h>                                
#include <linux/oprofile.h>                                
#include <linux/perf_event.h>                                
#include <linux/platform_device.h>                                
#include <linux/slab.h>                                
#include <asm/stacktrace.h>                                
#include <linux/uaccess.h>                                

#include <asm/perf_event.h>                                
#include <asm/ptrace.h>                                

#ifdef CONFIG_HW_PERF_EVENTS                                
/*                                
 * Per performance monitor configuration as set via oprofilefs.                                
 */                                
struct op_counter_config {                                
    unsigned long count;                            
    unsigned long enabled;                            
    unsigned long event;                            
    unsigned long unit_mask;                            
    unsigned long kernel;                            
    unsigned long user;                            
    struct perf_event_attr attr;                            
};                                

static int op_arm_enabled;                                
static DEFINE_MUTEX(op_arm_mutex);                                

static struct op_counter_config *counter_config;                                
static struct perf_event **perf_events[nr_cpumask_bits];                                
static int perf_num_counters_bak;                                

/*                                
 * Overflow callback for oprofile.                                
 */                                
static void op_overflow_handler(struct perf_event *event, int unused,                                
            struct perf_sample_data *data, struct pt_regs *regs)                    
{                                
    int id;                            
    u32 cpu = smp_processor_id();                            

    for (id = 0; id < perf_num_counters_bak; ++id)                            
        if (perf_events[cpu][id] == event)                        
            break;                    

    if (id != perf_num_counters_bak)                            
        oprofile_add_sample(regs, id);                        
    else                            
        pr_warning("oprofile: ignoring spurious overflow "                        
                on cpu %u\n, cpu);                
}                                

/*                                
 * Called by op_arm_setup to create perf attributes to mirror the oprofile                                
 * settings in counter_config. Attributes are created as `pinned' events and                                
 * so are permanently scheduled on the PMU.                                
 */                                
static void op_perf_setup(void)                                
{                                
    int i;                            
    u32 size = sizeof(struct perf_event_attr);                            
    struct perf_event_attr *attr;                            

    for (i = 0; i < perf_num_counters_bak; ++i) {                            
        attr = &counter_config[i].attr;                        
        memset(attr, 0, size);                        
        attr->type        = PERF_TYPE_RAW;                
        attr->size        = size;                
        attr->config        = counter_config[i].event;                
        attr->sample_period    = counter_config[i].count;                    
        attr->pinned        = 1;                
    }                            
}                                

static int op_create_counter(int cpu, int event)                                
{                                
    int ret = 0;                            
    struct perf_event *pevent;                            

    if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL))                            
        return ret;                        

    pevent = perf_event_create_kernel_counter(&counter_config[event].attr,                            
                          cpu, NULL,        
                          op_overflow_handler);        

    if (IS_ERR(pevent)) {                            
        ret = PTR_ERR(pevent);                        
    } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) {                            
        pr_warning("oprofile: failed to enable event %d "                        
                on CPU %d\n, event, cpu);                
        ret = -EBUSY;                        
    } else {                            
        perf_events[cpu][event] = pevent;                        
    }                            

    return ret;                            
}                                

static void op_destroy_counter(int cpu, int event)                                
{                                
    struct perf_event *pevent = perf_events[cpu][event];                            

    if (pevent) {                            
        perf_event_release_kernel(pevent);                        
        perf_events[cpu][event] = NULL;                        
    }                            
}                                

/*                                
 * Called by op_arm_start to create active perf events based on the                                
 * perviously configured attributes.                                
 */                                
static int op_perf_start(void)                                
{                                
    int cpu, event, ret = 0;                            

    for_each_online_cpu(cpu) {                            
        for (event = 0; event < perf_num_counters_bak; ++event) {                        
            ret = op_create_counter(cpu, event);                    
            if (ret)                    
                goto out;                
        }                        
    }                            

out:                                
    return ret;                            
}                                

/*                                
 * Called by op_arm_stop at the end of a profiling run.                                
 */                                
static void op_perf_stop(void)                                
{                                
    int cpu, event;                            

    for_each_online_cpu(cpu)                            
        for (event = 0; event < perf_num_counters_bak; ++event)                        
            op_destroy_counter(cpu, event);                    
}                                

char *op_name_from_perf_id(void)                                
{                                
    enum arm_perf_pmu_ids id = armpmu_get_pmu_id();                            

    switch (id) {                            
    case ARM_PERF_PMU_ID_XSCALE1:                            
        return "arm/xscale1";                        
    case ARM_PERF_PMU_ID_XSCALE2:                            
        return "arm/xscale2";                        
    case ARM_PERF_PMU_ID_V6:                            
        return "arm/armv6";                        
    case ARM_PERF_PMU_ID_V6MP:                            
        return "arm/mpcore";                        
    case ARM_PERF_PMU_ID_CA8:                            
        return "arm/armv7";                        
    case ARM_PERF_PMU_ID_CA9:                            
        return "arm/armv7-ca9";                        
    default:                            
        return NULL;                        
    }                            
}                                

static int op_arm_create_files(struct super_block *sb, struct dentry *root)                                
{                                
    unsigned int i;                            

    for (i = 0; i < perf_num_counters_bak; i++) {                            
        struct dentry *dir;                        
        char buf[4];                        

        snprintf(buf, sizeof buf, "%d", i);                        
        dir = oprofilefs_mkdir(sb, root, buf);                        
        oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);                        
        oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);                        
        oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);                        
        oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);                        
        oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);                        
        oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);                        
    }                            

    return 0;                            
}                                

static int op_arm_setup(void)                                
{                                
    spin_lock(&oprofilefs_lock);                            
    op_perf_setup();                            
    spin_unlock(&oprofilefs_lock);                            
    return 0;                            
}                                

static int op_arm_start(void)                                
{                                
    int ret = -EBUSY;                            

    mutex_lock(&op_arm_mutex);                            
    if (!op_arm_enabled) {                            
        ret = 0;                        
        op_perf_start();                        
        op_arm_enabled = 1;                        
    }                            
    mutex_unlock(&op_arm_mutex);                            
    return ret;                            
}                                

static void op_arm_stop(void)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled)                            
        op_perf_stop();                        
    op_arm_enabled = 0;                            
    mutex_unlock(&op_arm_mutex);                            
}                                

#ifdef CONFIG_PM                                
static int op_arm_suspend(struct platform_device *dev, pm_message_t state)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled)                            
        op_perf_stop();                        
    mutex_unlock(&op_arm_mutex);                            
    return 0;                            
}                                

static int op_arm_resume(struct platform_device *dev)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled && op_perf_start())                            
        op_arm_enabled = 0;                        
    mutex_unlock(&op_arm_mutex);                            
    return 0;                            
}                                

static struct platform_driver oprofile_driver = {                                
    .driver        = {                    
        .name        = "arm-oprofile",                
    },                            
    .resume        = op_arm_resume,                    
    .suspend    = op_arm_suspend,                        
};                                

static struct platform_device *oprofile_pdev;                                

static int __init init_driverfs(void)                                
{                                
    int ret;                            

    ret = platform_driver_register(&oprofile_driver);                            
    if (ret)                            
        goto out;                        

    oprofile_pdev =    platform_device_register_simple(                        
                oprofile_driver.driver.name, 0, NULL, 0);                
    if (IS_ERR(oprofile_pdev)) {                            
        ret = PTR_ERR(oprofile_pdev);                        
        platform_driver_unregister(&oprofile_driver);                        
    }                            

out:                                
    return ret;                            
}                                

static void  exit_driverfs(void)                                
{                                
    platform_device_unregister(oprofile_pdev);                            
    platform_driver_unregister(&oprofile_driver);                            
}                                
#else                                
static int __init init_driverfs(void) { return 0; }                                
#define exit_driverfs() do { } while (0)                                
#endif /* CONFIG_PM */                                

static int report_trace(struct stackframe *frame, void *d)                                
{                                
    unsigned int *depth = d;                            

    if (*depth) {                            
        oprofile_add_trace(frame->pc);                        
        (*depth)--;                        
    }                            

    return *depth == 0;                            
}                                

/*                                
 * The registers we're interested in are at the end of the variable                                
 * length saved register structure. The fp points at the end of this                                
 * structure so the address of this struct is:                                
 * (struct frame_tail *)(xxx->fp)-1                                
 */                                
struct frame_tail {                                
    struct frame_tail *fp;                            
    unsigned long sp;                            
    unsigned long lr;                            
} __attribute__((packed));                                

static struct frame_tail* user_backtrace(struct frame_tail *tail)                                
{                                
    struct frame_tail buftail[2];                            

    /* Also check accessibility of one struct frame_tail beyond */                            
    if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))                            
        return NULL;                        
    if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail)))                            
        return NULL;                        

    oprofile_add_trace(buftail[0].lr);                            

    /* frame pointers should strictly progress back up the stack                            
     * (towards higher addresses) */                            
    if (tail + 1 >= buftail[0].fp)                            
        return NULL;                        

    return buftail[0].fp-1;                            
}                                

static void arm_backtrace(struct pt_regs * const regs, unsigned int depth)                                
{                                
    struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;                            

    if (!user_mode(regs)) {                            
        struct stackframe frame;                        
        frame.fp = regs->ARM_fp;                        
        frame.sp = regs->ARM_sp;                        
        frame.lr = regs->ARM_lr;                        
        frame.pc = regs->ARM_pc;                        
        walk_stackframe(&frame, report_trace, &depth);                        
        return;                        
    }                            

    while (depth-- && tail && !((unsigned long) tail & 3))                            
        tail = user_backtrace(tail);                        
}                                

int __init oprofile_arch_init(struct oprofile_operations *ops)                                
{                                
    int cpu, ret = 0;                            

    perf_num_counters_bak = armpmu_get_max_events();                            

    counter_config = kcalloc(perf_num_counters_bak,                            
            sizeof(struct op_counter_config), GFP_KERNEL);                    

    if (!counter_config) {                            
        pr_info("oprofile: failed to allocate %d "                        
                counters\n, perf_num_counters_bak);                
        return -ENOMEM;                        
    }                            

    ret = init_driverfs();                            
    if (ret) {                            
        kfree(counter_config);                        
        return ret;                        
    }                            

    for_each_possible_cpu(cpu) {                            
        perf_events[cpu] = kcalloc(perf_num_counters_bak,                        
                sizeof(struct perf_event *), GFP_KERNEL);                
        if (!perf_events[cpu]) {                        
            pr_info("oprofile: failed to allocate %d perf events "                    
                    for cpu %d\n, perf_num_counters_bak, cpu);            
            while (--cpu >= 0)                    
                kfree(perf_events[cpu]);                
            return -ENOMEM;                    
        }                        
    }                            

    ops->backtrace        = arm_backtrace;                    
    ops->create_files    = op_arm_create_files;                        
    ops->setup        = op_arm_setup;                    
    ops->start        = op_arm_start;                    
    ops->stop        = op_arm_stop;                    
    ops->shutdown        = op_arm_stop;                    
    ops->cpu_type        = op_name_from_perf_id();                    

    if (!ops->cpu_type)                            
        ret = -ENODEV;                        
    else                            
        pr_info("oprofile: using %s\n", ops->cpu_type);                        

    return ret;                            
}                                

void oprofile_arch_exit(void)                                
{                                
    int cpu, id;                            
    struct perf_event *event;                            

    if (*perf_events) {                            
        exit_driverfs();                        
        for_each_possible_cpu(cpu) {                        
            for (id = 0; id < perf_num_counters_bak; ++id) {                    
                event = perf_events[cpu][id];                
                if (event != NULL)                
                    perf_event_release_kernel(event);            
            }                    
            kfree(perf_events[cpu]);                    
        }                        
    }                            

    if (counter_config)                            
        kfree(counter_config);                        
}                                

#else                                
int __init oprofile_arch_init(struct oprofile_operations *ops)                                
{                                
    pr_info("oprofile: hardware counters not available\n");                            
    return -ENODEV;                            
}                                
void oprofile_arch_exit(void) {}                                
#endif /* CONFIG_HW_PERF_EVENTS */

三、相关
kernel/sched.c——–profile_hit(SCHED_PROFILING,
__builtin_return_address(0));
上边是对profile的分解:Linux — profile内核版本2.6.18-RC7
profile只是基础的一个调节和测量检验品质的工具,那个能够通过menuconfig中的Instrumentation
Support->profile张开。

  1. 怎么选取profile:
    率先料定内核辅助profile,然后在基本运营时参与以下参数:profile=1可能别的参数,
    新的根本扶助profile=schedule 1
    2.
    内核运维后会创设/proc/profile文件,这一个文件能够因此readprofile读取,
    Android质量测量检验工具,oprofile质量深入分析。如readprofile -m /proc/kallsyms | sort -nr > ~/cur_profile.log,
    或者readprofile -r -m /proc/kallsyms |sort -nr,
    或者readprofile -r && sleep 1 && readprofile -m /proc/kallsyms |sort -nr
    >~/cur_profile.log
  2. 读取/proc/profile可获取怎么着内容?
    据书上说运营配置profile=?的不如,获取的从头到尾的经过不一:
    假使布置成profile=? 能够拿走种种函数推行次数,用来调治函数品质很有用
    万一设置成profile=schedule
    ?能够获取各样函数调用schedule的次数,用来调治schedule很有用

四、总计一下:
opcontrol –init 加载模块, mout /dev/oprofile 创制必需的文本和目录
opcontrol –no-vmlinux 或者 opcontrol –vmlinux=/boot/vmlinux-`uname
-r` 决定是还是不是对 kernel 举行 profiling
opcontrol –list-events //命令能够查阅此布局中协理的平地风波
opcontrol –event=CPU_CLK_UNHALTED:5000
–event=DATA_CACHE_MISSES:1000 –event=INSTRUCTION_CACHE_MISSES:1000
–event=MEMORY_REQUESTS:1000
opcontrol –reset 清楚当前对话中的数据
opcontrol –start 开始 profiling
./wls 运营应用程序, oprofile 会对它实行 profiling 通过opcontrol
–event=L2_CACHE_MISS:500
–event=L1_DTLB_MISS_AND_L2_DTLB_HIT:500
opcontrol –dump 把募集到的多寡写入文件
–event=………命令来开始展览事件的设置;
opcontrol –stop 截止 profiling
此命令–event参数必须逐项给出,无论有多少个,不可分行,切记
opcotrol -h 关闭守护进程 oprofiled
opcontrol –shutdown 停止 oprofiled
opcontrol –deinit 卸载模块

常用的是 3→7 那多少个进程,获得质量数据之后,能够利用 opreport, opstack,
opgprof, opannotate多少个工具举行分析,小编常用的是
opreport, opannotate 举办深入分析。

五、示例与普及难题解诀
Command format :$:tager board, #:Host
1.Extract opf.tar.gz and busybox.tar.gz ($: tar -zxvf ***.tar.gz)
2.Use adb push opf to /data/opf and busybox to /data/busybox
(#: adb push opf /data/opf and #: adb push busybox /data/busybox)
3.Run $:export PATH=$PATH:/data/opf

$: is command to begin
4.Run $:opcontrol –init

Remark: if target board have oprofile,please delete the
files(path:/system/xbin)

Question:
grep: /etc/mtab: No such file or directory
grep: /etc/mtab: No such file or directory
Kernel support not available, missing opcontrol –init as root

Answer:
a.$:mount -o remount rw /
b.$:mount -o rw,remount -t yaffs2 /dev/block/mmcblk0p9 /system
c.$:touch /system/etc/mtab or touch /etc/mtab
d.$:echo nodev /dev/oprofile oprofilefs rw 0 0 > /system/etc/mtab or
/etc/mtab
e.make sure mtab the nodev $:cat /system/etc/mtab

5.$:opcontrol –init

Question:
cat: can’t open ‘/dev/oprofile/cpu_type’: No such file or directory
Unable to open cpu_type file for reading
Make sure you have done opcontrol –init
cpu_type ‘unset’ is not valid
you should upgrade oprofile or force the use of timer mode

Answer:
a.$:mkdir /dev/oprofile (if not exist)
b.mount -t oprofilefs nodev /dev/oprofile

6.$:opcontrol –session-dir=/data/first –no-vmlinux –callgraph=5

7.$:opcontrol –start

Question:
oprofile: could not open unit mask description file
/home/henry/workspace/opf/pc/build/oprofile/share/oprofile//arm/armv7-ca9/unit_masks
Using default event: CPU_CYCLES:100000:0:1:1
oprofile: could not open unit mask description file
/home/henry/workspace/opf/pc/build/oprofile/share/oprofile//arm/armv7-ca9/unit_masks

Answer:
a.To target board running $:mkdir -p
/home/henry/workspace/opf/pc/build/oprofile
b.Extract share.tar.gz
c.Use ADB push share (#:adb push share
/home/henry/workspace/opf/pc/build/oprofile/share)

8.Run App to profile
9.$:opcontrol –dump
10.$:opcontrol –stop
11.$:opreport –session-dir=/data/first -l /data/test/test
$:opreport –session-dir=/data/first -l >log
$:opreport –session-dir=/data/first -l /data/data/Service/lib/libXXX.so
>logXXX
$:opreport –session-dir=/data/first -l /data/data/Service/lib/libBBB.so
>logBBB
12.$:opcontrol –reset
13.opcontrol –shutdown

Remark: $:opcontrol –shutdown and $:opcontrol –init only execution
once

一、内核帮助:
make menuconfig

首先明确你的木本是还是不是增添了对oprofile
的支撑,方法是看基础的启航音信,要是有如下两行的,说明你的基本帮助oprofile:

XP会不会比98更为丰裕的发表硬件的性能够,进而使游戏运转更顺畅?

作为服兵役十余年的类别,它曾经迎来了谐和的归宿。未来,满世界的网上朋友不禁为这一不屈存在于microsoft十余载的系统肃然生敬。独有任何时间任何地方地商量、尝试、立异,手艺使系统运转更人性化。这点,是XP不可能与7和8.1相抗衡的。
 

1、评测菜单中启用 Oprofile ,在 .config
文件中装置?CONFIG_PROFILING=y?和?CONFIG_OPROFILE=y
2、Kernel Feature->[]Enable hardware performance counter support
for perf events不要勾选
3、在boot options->console=ttyFIQ0 androidboot.console=ttyFIQ0
init=/init profile=1
二、修改源码 将kernel/arch/arm/oprofile中的common.文件修改

Android应用的品质如何测验?JAVA层面能够用TraceView,可是用NDK开垦出来的是so,TraceView追踪不了如何是好?问了谷歌大神,答案是OProfile!

oprofile: hardware counters not available

O形橡胶密闭圈在介质压力成效下的有限元分析,怎在截面包车型地铁左边加介质的下压力?

不晓得您的介质指什么?作者的理解是您要加在O形圈的内侧边,来效仿所受液体/气体的压力。如若你用的平面剖析,则加在内侧线上,方向指向O形圈圆心。倘令你是三维模型,则一贯加在内左边上,方向指向O形圈圆心。
 

oprofile质量深入分析),androidoprofile 一、内核扶助: make menuconfig
1、评测菜单中启用 Oprofile ,在 .config 文件中设置?CONFIG_PR…

/**                                
 * @file common.c                                
 *                                
 * @remark Copyright 2004 Oprofile Authors                                
 * @remark Copyright 2010 ARM Ltd.                                
 * @remark Read the file COPYING                                
 *                                
 * @author Zwane Mwaikambo                                
 * @author Will Deacon [move to perf]                                
 */                                

#include <linux/cpumask.h>                                
#include <linux/err.h>                                
#include <linux/errno.h>                                
#include <linux/init.h>                                
#include <linux/mutex.h>                                
#include <linux/oprofile.h>                                
#include <linux/perf_event.h>                                
#include <linux/platform_device.h>                                
#include <linux/slab.h>                                
#include <asm/stacktrace.h>                                
#include <linux/uaccess.h>                                

#include <asm/perf_event.h>                                
#include <asm/ptrace.h>                                

#ifdef CONFIG_HW_PERF_EVENTS                                
/*                                
 * Per performance monitor configuration as set via oprofilefs.                                
 */                                
struct op_counter_config {                                
    unsigned long count;                            
    unsigned long enabled;                            
    unsigned long event;                            
    unsigned long unit_mask;                            
    unsigned long kernel;                            
    unsigned long user;                            
    struct perf_event_attr attr;                            
};                                

static int op_arm_enabled;                                
static DEFINE_MUTEX(op_arm_mutex);                                

static struct op_counter_config *counter_config;                                
static struct perf_event **perf_events[nr_cpumask_bits];                                
static int perf_num_counters_bak;                                

/*                                
 * Overflow callback for oprofile.                                
 */                                
static void op_overflow_handler(struct perf_event *event, int unused,                                
            struct perf_sample_data *data, struct pt_regs *regs)                    
{                                
    int id;                            
    u32 cpu = smp_processor_id();                            

    for (id = 0; id < perf_num_counters_bak; ++id)                            
        if (perf_events[cpu][id] == event)                        
            break;                    

    if (id != perf_num_counters_bak)                            
        oprofile_add_sample(regs, id);                        
    else                            
        pr_warning("oprofile: ignoring spurious overflow "                        
                on cpu %u\n, cpu);                
}                                

/*                                
 * Called by op_arm_setup to create perf attributes to mirror the oprofile                                
 * settings in counter_config. Attributes are created as `pinned' events and                                
 * so are permanently scheduled on the PMU.                                
 */                                
static void op_perf_setup(void)                                
{                                
    int i;                            
    u32 size = sizeof(struct perf_event_attr);                            
    struct perf_event_attr *attr;                            

    for (i = 0; i < perf_num_counters_bak; ++i) {                            
        attr = &counter_config[i].attr;                        
        memset(attr, 0, size);                        
        attr->type        = PERF_TYPE_RAW;                
        attr->size        = size;                
        attr->config        = counter_config[i].event;                
        attr->sample_period    = counter_config[i].count;                    
        attr->pinned        = 1;                
    }                            
}                                

static int op_create_counter(int cpu, int event)                                
{                                
    int ret = 0;                            
    struct perf_event *pevent;                            

    if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL))                            
        return ret;                        

    pevent = perf_event_create_kernel_counter(&counter_config[event].attr,                            
                          cpu, NULL,        
                          op_overflow_handler);        

    if (IS_ERR(pevent)) {                            
        ret = PTR_ERR(pevent);                        
    } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) {                            
        pr_warning("oprofile: failed to enable event %d "                        
                on CPU %d\n, event, cpu);                
        ret = -EBUSY;                        
    } else {                            
        perf_events[cpu][event] = pevent;                        
    }                            

    return ret;                            
}                                

static void op_destroy_counter(int cpu, int event)                                
{                                
    struct perf_event *pevent = perf_events[cpu][event];                            

    if (pevent) {                            
        perf_event_release_kernel(pevent);                        
        perf_events[cpu][event] = NULL;                        
    }                            
}                                

/*                                
 * Called by op_arm_start to create active perf events based on the                                
 * perviously configured attributes.                                
 */                                
static int op_perf_start(void)                                
{                                
    int cpu, event, ret = 0;                            

    for_each_online_cpu(cpu) {                            
        for (event = 0; event < perf_num_counters_bak; ++event) {                        
            ret = op_create_counter(cpu, event);                    
            if (ret)                    
                goto out;                
        }                        
    }                            

out:                                
    return ret;                            
}                                

/*                                
 * Called by op_arm_stop at the end of a profiling run.                                
 */                                
static void op_perf_stop(void)                                
{                                
    int cpu, event;                            

    for_each_online_cpu(cpu)                            
        for (event = 0; event < perf_num_counters_bak; ++event)                        
            op_destroy_counter(cpu, event);                    
}                                

char *op_name_from_perf_id(void)                                
{                                
    enum arm_perf_pmu_ids id = armpmu_get_pmu_id();                            

    switch (id) {                            
    case ARM_PERF_PMU_ID_XSCALE1:                            
        return "arm/xscale1";                        
    case ARM_PERF_PMU_ID_XSCALE2:                            
        return "arm/xscale2";                        
    case ARM_PERF_PMU_ID_V6:                            
        return "arm/armv6";                        
    case ARM_PERF_PMU_ID_V6MP:                            
        return "arm/mpcore";                        
    case ARM_PERF_PMU_ID_CA8:                            
        return "arm/armv7";                        
    case ARM_PERF_PMU_ID_CA9:                            
        return "arm/armv7-ca9";                        
    default:                            
        return NULL;                        
    }                            
}                                

static int op_arm_create_files(struct super_block *sb, struct dentry *root)                                
{                                
    unsigned int i;                            

    for (i = 0; i < perf_num_counters_bak; i++) {                            
        struct dentry *dir;                        
        char buf[4];                        

        snprintf(buf, sizeof buf, "%d", i);                        
        dir = oprofilefs_mkdir(sb, root, buf);                        
        oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);                        
        oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);                        
        oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);                        
        oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);                        
        oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);                        
        oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);                        
    }                            

    return 0;                            
}                                

static int op_arm_setup(void)                                
{                                
    spin_lock(&oprofilefs_lock);                            
    op_perf_setup();                            
    spin_unlock(&oprofilefs_lock);                            
    return 0;                            
}                                

static int op_arm_start(void)                                
{                                
    int ret = -EBUSY;                            

    mutex_lock(&op_arm_mutex);                            
    if (!op_arm_enabled) {                            
        ret = 0;                        
        op_perf_start();                        
        op_arm_enabled = 1;                        
    }                            
    mutex_unlock(&op_arm_mutex);                            
    return ret;                            
}                                

static void op_arm_stop(void)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled)                            
        op_perf_stop();                        
    op_arm_enabled = 0;                            
    mutex_unlock(&op_arm_mutex);                            
}                                

#ifdef CONFIG_PM                                
static int op_arm_suspend(struct platform_device *dev, pm_message_t state)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled)                            
        op_perf_stop();                        
    mutex_unlock(&op_arm_mutex);                            
    return 0;                            
}                                

static int op_arm_resume(struct platform_device *dev)                                
{                                
    mutex_lock(&op_arm_mutex);                            
    if (op_arm_enabled && op_perf_start())                            
        op_arm_enabled = 0;                        
    mutex_unlock(&op_arm_mutex);                            
    return 0;                            
}                                

static struct platform_driver oprofile_driver = {                                
    .driver        = {                    
        .name        = "arm-oprofile",                
    },                            
    .resume        = op_arm_resume,                    
    .suspend    = op_arm_suspend,                        
};                                

static struct platform_device *oprofile_pdev;                                

static int __init init_driverfs(void)                                
{                                
    int ret;                            

    ret = platform_driver_register(&oprofile_driver);                            
    if (ret)                            
        goto out;                        

    oprofile_pdev =    platform_device_register_simple(                        
                oprofile_driver.driver.name, 0, NULL, 0);                
    if (IS_ERR(oprofile_pdev)) {                            
        ret = PTR_ERR(oprofile_pdev);                        
        platform_driver_unregister(&oprofile_driver);                        
    }                            

out:                                
    return ret;                            
}                                

static void  exit_driverfs(void)                                
{                                
    platform_device_unregister(oprofile_pdev);                            
    platform_driver_unregister(&oprofile_driver);                            
}                                
#else                                
static int __init init_driverfs(void) { return 0; }                                
#define exit_driverfs() do { } while (0)                                
#endif /* CONFIG_PM */                                

static int report_trace(struct stackframe *frame, void *d)                                
{                                
    unsigned int *depth = d;                            

    if (*depth) {                            
        oprofile_add_trace(frame->pc);                        
        (*depth)--;                        
    }                            

    return *depth == 0;                            
}                                

/*                                
 * The registers we're interested in are at the end of the variable                                
 * length saved register structure. The fp points at the end of this                                
 * structure so the address of this struct is:                                
 * (struct frame_tail *)(xxx->fp)-1                                
 */                                
struct frame_tail {                                
    struct frame_tail *fp;                            
    unsigned long sp;                            
    unsigned long lr;                            
} __attribute__((packed));                                

static struct frame_tail* user_backtrace(struct frame_tail *tail)                                
{                                
    struct frame_tail buftail[2];                            

    /* Also check accessibility of one struct frame_tail beyond */                            
    if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))                            
        return NULL;                        
    if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail)))                            
        return NULL;                        

    oprofile_add_trace(buftail[0].lr);                            

    /* frame pointers should strictly progress back up the stack                            
     * (towards higher addresses) */                            
    if (tail + 1 >= buftail[0].fp)                            
        return NULL;                        

    return buftail[0].fp-1;                            
}                                

static void arm_backtrace(struct pt_regs * const regs, unsigned int depth)                                
{                                
    struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;                            

    if (!user_mode(regs)) {                            
        struct stackframe frame;                        
        frame.fp = regs->ARM_fp;                        
        frame.sp = regs->ARM_sp;                        
        frame.lr = regs->ARM_lr;                        
        frame.pc = regs->ARM_pc;                        
        walk_stackframe(&frame, report_trace, &depth);                        
        return;                        
    }                            

    while (depth-- && tail && !((unsigned long) tail & 3))                            
        tail = user_backtrace(tail);                        
}                                

int __init oprofile_arch_init(struct oprofile_operations *ops)                                
{                                
    int cpu, ret = 0;                            

    perf_num_counters_bak = armpmu_get_max_events();                            

    counter_config = kcalloc(perf_num_counters_bak,                            
            sizeof(struct op_counter_config), GFP_KERNEL);                    

    if (!counter_config) {                            
        pr_info("oprofile: failed to allocate %d "                        
                counters\n, perf_num_counters_bak);                
        return -ENOMEM;                        
    }                            

    ret = init_driverfs();                            
    if (ret) {                            
        kfree(counter_config);                        
        return ret;                        
    }                            

    for_each_possible_cpu(cpu) {                            
        perf_events[cpu] = kcalloc(perf_num_counters_bak,                        
                sizeof(struct perf_event *), GFP_KERNEL);                
        if (!perf_events[cpu]) {                        
            pr_info("oprofile: failed to allocate %d perf events "                    
                    for cpu %d\n, perf_num_counters_bak, cpu);            
            while (--cpu >= 0)                    
                kfree(perf_events[cpu]);                
            return -ENOMEM;                    
        }                        
    }                            

    ops->backtrace        = arm_backtrace;                    
    ops->create_files    = op_arm_create_files;                        
    ops->setup        = op_arm_setup;                    
    ops->start        = op_arm_start;                    
    ops->stop        = op_arm_stop;                    
    ops->shutdown        = op_arm_stop;                    
    ops->cpu_type        = op_name_from_perf_id();                    

    if (!ops->cpu_type)                            
        ret = -ENODEV;                        
    else                            
        pr_info("oprofile: using %s\n", ops->cpu_type);                        

    return ret;                            
}                                

void oprofile_arch_exit(void)                                
{                                
    int cpu, id;                            
    struct perf_event *event;                            

    if (*perf_events) {                            
        exit_driverfs();                        
        for_each_possible_cpu(cpu) {                        
            for (id = 0; id < perf_num_counters_bak; ++id) {                    
                event = perf_events[cpu][id];                
                if (event != NULL)                
                    perf_event_release_kernel(event);            
            }                    
            kfree(perf_events[cpu]);                    
        }                        
    }                            

    if (counter_config)                            
        kfree(counter_config);                        
}                                

#else                                
int __init oprofile_arch_init(struct oprofile_operations *ops)                                
{                                
    pr_info("oprofile: hardware counters not available\n");                            
    return -ENODEV;                            
}                                
void oprofile_arch_exit(void) {}                                
#endif /* CONFIG_HW_PERF_EVENTS */

Oprofile
是Linux系统下三个低费用的体系全局的习性监视工具,利用Computer上所含有的专项使用的属性监视硬件(若未有品质监视硬件则运用二个基于停车计时器的代用品)来访谈与天性相关的数据样品。它获得有关基本以及系统上的可推行文件的音讯,举例内部存款和储蓄器是何时被引用的;L2缓存诉求的数额;收到的硬件中断数量等。

oprofile: using timer interrupt.

三、相关
kernel/sched.c——–profile_hit(SCHED_PROFILING,
__builtin_return_address(0));
上面是对profile的解说:Linux — profile内核版本2.6.18-RC7
profile只是内核的二个调和质量的工具,这几个能够通过menuconfig中的Instrumentation
Support->profile张开。

Oprofile的特点如下:

假定没有就需求在基本中增多对oprofile的支撑:

  1. 怎么着选取profile:
    率先确定内核补助profile,然后在基本运转时参预以下参数:profile=1也许另外参数,
    新的根本扶助profile=schedule 1
    2.
    内核运维后会创设/proc/profile文件,这一个文件能够因此readprofile读取,
    如readprofile -m /proc/kallsyms | sort -nr > ~/cur_profile.log,
    或者readprofile -r -m /proc/kallsyms |sort -nr,
    或者readprofile -r && sleep 1 && readprofile -m /proc/kallsyms |sort -nr
    >~/cur_profile.log
  2. 读取/proc/profile可得到怎么样内容?
    据他们说运营配置profile=?的不如,获取的源委不一:
    若是布署成profile=? 能够收获每一个函数实行次数,用来调度函数质量很有用
    一旦设置成profile=schedule
    ?能够赢得每一个函数调用schedule的次数,用来调解schedule很有用

l         不需求另行编写翻译源代码,假若不举办源代码及剖析,连调试音信(-g
option to gcc)亦非必须的。

1 在/arch/unicore(根据你的实在情状)/ 下树立oprofile 文件夹
,在oprofile中是makefile 将/driver/oprofile中的文件编写翻译

四、总计一下:
opcontrol –init 加载模块, mout /dev/oprofile 创立必需的文本和目录
opcontrol –no-vmlinux 或者 opcontrol –vmlinux=/boot/vmlinux-`uname
-r` 决定是不是对 kernel 实行 profiling
opcontrol –list-events //命令能够查阅此布局中补助的事件
opcontrol –event=CPU_CLK_UNHALTED:5000
–event=DATA_CACHE_MISSES:1000 –event=INSTRUCTION_CACHE_MISSES:1000
–event=MEMORY_REQUESTS:1000
opcontrol –reset 清楚当前对话中的数据
opcontrol –start 开始 profiling
./wls 运转应用程序, oprofile 会对它进行 profiling 通过opcontrol
–event=L2_CACHE_MISS:500
–event=L1_DTLB_MISS_AND_L2_DTLB_HIT:500
opcontrol –dump 把访谈到的数目写入文件
–event=………命令来开展事件的设置;
opcontrol –stop 结束 profiling
此命令–event参数必须逐个给出,无论有多少个,不可分行,切记
opcotrol -h 关闭守护进程 oprofiled
opcontrol –shutdown 停止 oprofiled
opcontrol –deinit 卸载模块

l         只在根本中插入二个模块。

2 在/arch/unicore/kconfig 中将 config STACKTRACE_SUPPORT default 选为 y

常用的是 3→7 那多少个进程,获得质量数据之后,能够动用 opreport, opstack,
opgprof, opannotate多少个工具进行深入分析,我常用的是
opreport, opannotate 实行深入分析。

l         能够深入分析运营于系统之上的富有代码(禁止使用中断的代码除此而外)

3 make menuconfig 添加oprofile选项 make menuconfig general step 中
profiling support 和 oprofile system profiling

五、示例与科普难点解诀
Command format :$:tager board, #:Host
1.Extract opf.tar.gz and busybox.tar.gz ($: tar -zxvf ***.tar.gz)
2.Use adb push opf to /data/opf and busybox to /data/busybox
(#: adb push opf /data/opf and #: adb push busybox /data/busybox)
3.Run $:export PATH=$PATH:/data/opf

l        
系统的额外开支小,Oprofile会扩展1%-8%的系统开荒(取决于采集样品频率)

如此就好了。

$: is command to begin
4.Run $:opcontrol –init

l         包容全部2.2,2.4,2.6内核,能够运营在SMP系统之上

美高梅手机版4858 1

Remark: if target board have oprofile,please delete the
files(path:/system/xbin)

l         协理主流CPU架构,包含X86、arm、AV酷路泽32、mips、powerpc等

Question:
grep: /etc/mtab: No such file or directory
grep: /etc/mtab: No such file or directory
Kernel support not available, missing opcontrol –init as root

Oprofile要想跑在Andorid上,要满意上面包车型大巴法规:

Answer:
a.$:mount -o remount rw /
b.$:mount -o rw,remount -t yaffs2 /dev/block/mmcblk0p9 /system
c.$:touch /system/etc/mtab or touch /etc/mtab
d.$:echo nodev /dev/oprofile oprofilefs rw 0 0 > /system/etc/mtab or
/etc/mtab
e.make sure mtab the nodev $:cat /system/etc/mtab

1.内核要支持

5.$:opcontrol –init

2.要将Oprofile移植到Arm平台上

Question:
cat: can’t open ‘/dev/oprofile/cpu_type’: No such file or directory
Unable to open cpu_type file for reading
Make sure you have done opcontrol –init
cpu_type ‘unset’ is not valid
you should upgrade oprofile or force the use of timer mode

 

Answer:
a.$:mkdir /dev/oprofile (if not exist)
b.mount -t oprofilefs nodev /dev/oprofile

上面是移植的全经过:

6.$:opcontrol –session-dir=/data/first –no-vmlinux –callgraph=5

一、Oprofile移植

7.$:opcontrol –start

用到的时断时续编写翻译工具如下:

Question:
oprofile: could not open unit mask description file
/home/henry/workspace/opf/pc/build/oprofile/share/oprofile//arm/armv7-ca9/unit_masks
Using default event: CPU_CYCLES:100000:0:1:1
oprofile: could not open unit mask description file
/home/henry/workspace/opf/pc/build/oprofile/share/oprofile//arm/armv7-ca9/unit_masks

arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

Answer:
a.To target board running $:mkdir -p
/home/henry/workspace/opf/pc/build/oprofile
b.Extract share.tar.gz
c.Use ADB push share (#:adb push share
/home/henry/workspace/opf/pc/build/oprofile/share)

用到的库如下:

8.Run App to profile
9.$:opcontrol –dump
10.$:opcontrol –stop
11.$:opreport –session-dir=/data/first -l /data/test/test
$:opreport –session-dir=/data/first -l >log
$:opreport –session-dir=/data/first -l /data/data/Service/lib/libXXX.so
>logXXX
$:opreport –session-dir=/data/first -l /data/data/Service/lib/libBBB.so
>logBBB
12.$:opcontrol –reset
13.opcontrol –shutdown

popt-1.14.tar.gz 

Remark: $:opcontrol –shutdown and $:opcontrol –init only execution
once

binutils-2.21.tar.gz

oprofile-0.9.6.tar.gz

 

$ tar xvfz
arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C ~/

修改~/.bashrc,添加

export PATH=${PATH}:/home/louieli/arm-2010.09/bin

 

$ tar zxvf popt-1.14.tar.gz 

$ cd popt-1.14

$ ac_cv_va_copy=yes ./configure –with-kernel-support
–host=arm-none-linux-gnueabi –prefix=/home/louieli/work/popt

$ make

$ make install

 

$ tar zxvf binutils-2.21.tar.gz

$ cd binutils-2.21/

$ ./configure –with-kernel-support –host=arm-none-linux-gnueabi
–prefix=/home/louieli/work/binutils –enable-shared

$ make LDFLAGS=”-all-static”

唯恐会合世 cc1: warnings being treated as
errors,找到出错文件的Makefile文件,将-Werror去掉

$ make install

 

$ tar zxvf oprofile-0.9.6.tar.gz

$ cd oprofile-0.9.6/

$ ./configure –with-kernel-support –host=arm-none-linux-gnueabi
–prefix=/home/louieli/work/oprofile/
–with-extra-libs=/home/louieli/work/popt/lib/
–with-extra-includes=/home/louieli/work/popt/include/
–with-binutils=/home/louieli/work/binutils

$ make LDFLAGS=”-all-static -L/home/louieli/work/binutils/lib -Xlinker
-R -Xlinker /home/louieli/work/binutils/lib
 -L/home/louieli/work/popt/lib/”

$ make install

用file
命令查看,大家须要的oprofile文件都早已化为能够在android上跑的静态链接文件了

install.sh: Bourne-Again shell script text executable

opannotate: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

oparchive:  ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

opcontrol:  a /system/bin/sh script text executable

opgprof:    ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

ophelp:     ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

opimport:   ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

opjitconv:  ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

opreport:   ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

oprofiled:  ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically
linked, for GNU/Linux 2.6.16, not stripped

 

 

二、编写翻译linux内核影象

a)妄图交叉编写翻译工具链

android代码树中有一个prebuilt项目,满含了我们编译内核所需的穿插编写翻译工具。

 

b)设定环境变量

$ emacs ~/.bashrc

日增如下两行:

export
PATH=$PATH:~/android/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin

export ARCH=arm

保留后,同步转移:

$ source ~/.bashrc

 

c)获得适当的内核源代码

$ cd ~/android

赢得内核源代码旅馆

$ git clone git://android.git.kernel.org/kernel/common.git kernel

$ cd kernel

$ git branch

显示

* android-2.6.27

注明你今后在android-2.6.27那么些分支上,也是kernel/common.git的暗中认可主分支。

突显全部head分支:

$ git branch -a

显示

* android-2.6.27

remotes/origin/HEAD -> origin/android-2.6.27

remotes/origin/android-2.6.25

remotes/origin/android-2.6.27

remotes/origin/android-2.6.29

remotes/origin/android-goldfish-2.6.27

remotes/origin/android-goldfish-2.6.29

大家选拔最新的android-goldfish-2.6.29,在这之中goldfish是android的模拟器模拟的CPU。

$ git checkout -b android-goldfish-2.6.29 origin/android-goldfish-2.6.29

$ git branch

显示

android-2.6.27

* android-goldfish-2.6.29

咱俩早已专门的职业在android-goldfish-2.6.29分支上了。

 

d)设定交叉编写翻译参数

打开kernel目录下的Makefile文件,把CROSS_COMPILE指向刚刚下载的prebuilt中的arm-eabi编写翻译器

CROSS_COMPILE ?= arm-eabi-

LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,/

$(call ld-option, -Wl$(comma)–build-id,))

这一行注释掉,何况增进四个空的LDFLAGS_BUILD_ID定义,如下:

LDFLAGS_BUILD_ID =

 

e)编写翻译内核影像

$ cd ~/android/kernel

$ make goldfish_defconfig

$ make menuconfig

修改内核配置如下

General setup —>

[*] Profiling support (EXPERIMENTAL)

[ ] Activate markers

[*] OProfile system profiling (EXPERIMENTAL) 

那是把OProfile直接编进内核,也得以选取[M] OProfile system profiling
(EXPE兰德CR-VIMENTAL)会在arch/arm/oprofile文件夹下生成oprofile.ko,oprofile.ko须要用insmod载入。

$make 

 

f)测量检验生成的内核影象

$ emulator -avd myavd -kernel ~/android/kernel/arch/arm/boot/zImage

 

三、Oprofile在android模拟器中的使用

1.先看一下opcontrol的参数

# opcontrol

opcontrol: usage:

   -l/–list-events list event types and unit masks

   -?/–help        this message

   -v/–version     show version

   –init           loads the oprofile module and oprofilefs

   –setup          give setup arguments (may be omitted)

   –status         show configuration

   –start-daemon   start daemon without starting profiling

   -s/–start       start data collection

   -d/–dump        flush the collected profiling data

   -t/–stop        stop data collection

   -h/–shutdown    stop data collection and kill daemon

   -V/–verbose[=all,sfile,arcs,samples,module,misc,ext]

                    be verbose in the daemon log

   –reset          clears out data from current session

   –save=name      save data from current session to session_name

   –deinit         unload the oprofile module and oprofilefs

   -e/–event=eventspec

      Choose an event. May be specified multiple times. Of the form

      “default” or “name:count:unitmask:kernel:user”, where :

      name:     event name, e.g. CPU_CLK_UNHALTED or RTC_INTERRUPTS

      count:    reset counter value e.g. 100000

      unitmask: hardware unit mask e.g. 0x0f

      kernel:   whether to profile kernel: 0 or 1

      user:     whether to profile userspace: 0 or 1

   -p/–separate=type,[types]

       Separate profiles as follows :

       none:     no profile separation

       library:  separate shared library profiles per-application

       kernel:   same as library, plus kernel profiles

       thread:   per-thread/process profiles

       cpu:      per CPU profiles

       all:      all of the above

   -c/–callgraph=#depth         enable callgraph sample collection
with a maximum depth.

                                 Use 0 to disable callgraph profiling.

   –session-dir=dir             place sample database in dir instead of

美高梅手机版4858 ,                                 default location (/var/lib/oprofile)

   -i/–image=name[,names]       list of binaries to profile (default
is “all”)

   –vmlinux=file                vmlinux kernel image

   –no-vmlinux                  no kernel image (vmlinux) available

   –kernel-range=start,end      kernel range vma address in hexadecimal

   –buffer-size=num             kernel buffer size in sample units

   –buffer-watershed            kernel buffer watershed in sample units
(2.6 only=

   –cpu-buffer-size=num         per-cpu buffer size in units (2.6 only)

   –note-table-size             kernel notes buffer size in notes units
(2.4 only)

 

   –xen                         Xen image (for Xen only)

   –active-domains=<list>       List of domains in profiling
session (for Xen only)

                                 (list contains domain ids separated by
commas)

 

 

 

2.利用方法

将大家事先编写翻译好的oprofile和busybox装入模拟器

执行oprofile目录中的install.sh 将oprofile装入模拟器

adb push busybox /data/busybox

$adb shell  //步入模拟器shell

#chmod 777 /data/busybox

# /data/busybox –install /data/busybox

#export PATH=/data/busybox:$PATH:/data/oprofile

# mount -o remount rw /

# mount -o rw,remount -t yaffs2 /dev/mtdblock3 /system

# touch /etc/mtab

# echo nodev /dev/oprofile oprofilefs rw 0 0>/etc/mtab

# mkdir /dev/oprofile

# mount -t oprofilefs nodev /dev/oprofile  
 //这一句很着重,没有这一句会油然则生上面包车型大巴一无可取

 

# opcontrol –init      

cat: can’t open ‘/dev/oprofile/cpu_type’: No such file or directory

Unable to open cpu_type file for reading

Make sure you have done opcontrol –init

cpu_type ‘unset’ is not valid

you should upgrade oprofile or force the use of timer mode

 

# opcontrol –init     //早先化,只需运转二遍

# opcontrol –setup –callgraph=2 –session-dir=/data/first
–no-vmlinux

Using 2.6+ OProfile kernel interface.

Using log file /data/first/samples/oprofiled.log

Daemon started.

Profiler running.

# opcontrol –status

Daemon running: pid 637

Separate options: none

vmlinux file: none

Image filter: none

Call-graph depth: 2

# opcontrol –start     //启动profiler

Using 2.6+ OProfile kernel interface.

Using log file /var/lib/oprofile/samples/oprofiled.log

Daemon started.

Profiler running.

# /data/test/test     //运维大家的程序 (
作者的测验程序通过那条指令编写翻译arm-none-linux-gnueabi-gcc -g -o test test.c
-static -fno-omit-frame-pointer)

in c

in a

in b

in a

in c

in b

in a

in a

# opcontrol –dump   //搜罗采样数据

# opcontrol –stop //停止profiler

Stopping profiling.

#opreport –session-dir=/data/first -l /data/test/test       //查看报告

CPU: CPU with timer interrupt, speed 0 MHz (estimated)

Profiling through timer interrupt

samples  %        symbol name

11291    79.9589  a

1129      7.9952  b

853       6.0406  main

848       6.0052  c

昨天大家就能够根据oprofile的出口对大家的次第进行优化了。

譬如有哪位同学也想试一把的话,绝对要用linux。这种移植境况很关键,小编事先就在测量检验机(win7+cygwin)上浪费了不知凡什么日期日。这里有打包好的工具,大家能够下载。其中kernel-qemu正是大家前边编写翻译好的基业,替换掉Android
SDK中的kernel-qemu就行了。祝各位好运!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有