C++程序  |  247行  |  6.37 KB

/**
 * @file arrange_profiles.h
 * Classify and process a list of candidate sample files
 * into merged sets and classes.
 *
 * @remark Copyright 2003 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 */

#ifndef ARRANGE_PROFILES_H
#define ARRANGE_PROFILES_H

#include <string>
#include <list>
#include <vector>
#include <iosfwd>

#include "image_errors.h"
#include "locate_images.h"

/**
 * store merging options options used to classify profiles
 */
struct merge_option {
	bool cpu;
	bool lib;
	bool tid;
	bool tgid;
	bool unitmask;
};


/**
 * This describes which parameters are set for each
 * equivalence class.
 */
struct profile_template {
	std::string event;
	std::string count;
	std::string unitmask;
	std::string tgid;
	std::string tid;
	std::string cpu;
};


/**
 * A samples filename + its associated callgraph sample filename.
 */
struct profile_sample_files {
	/**
	 * This member can be empty since it is possible to get callgraph
	 * w/o any samples to the binary. e.g an application which defer all
	 * works to shared library but if arrange_profiles receive a sample
	 * file list filtered from cg file sample_filename can't be empty
	 */
	std::string sample_filename;
	/**
	 * List of callgraph sample filename. If the {dep} part of
	 * cg_filename != {cg} part it's a cross binary samples file.
	 */
	std::list<std::string> cg_files;
};


/**
 * A number of profiles files that are all dependent on
 * the same main (application) profile, for the same
 * dependent image.
 */
struct profile_dep_set {
	/// which dependent image is this set for
	std::string lib_image;

	/// the actual sample files optionnaly including callgraph sample files
	std::list<profile_sample_files> files;
};

/**
 * A number of profile files all for the same binary with the same
 * profile specification (after merging). Includes the set of dependent
 * profile files, if any.
 *
 * For example, we could have image == "/bin/bash", where files
 * contains all profiles against /bin/bash, and deps contains
 * the sample file list for /lib/libc.so, /lib/ld.so etc.
 */
struct profile_set {
	std::string image;

	/// the actual sample files for the main image and the asociated
	/// callgraph files
	std::list<profile_sample_files> files;

	/// all profile files dependent on the main image
	std::list<profile_dep_set> deps;
};


/**
 * A class collection of profiles. This is an equivalence class and
 * will correspond to columnar output of opreport.
 */
struct profile_class {
	std::list<profile_set> profiles;

	/// human-readable column name
	std::string name;

	/// human-readable long name
	std::string longname;

	/// merging matches against this
	profile_template ptemplate;
};


/**
 * The "axis" says what we've used to split the sample
 * files into the classes. Only one is allowed.
 */
enum axis_types {
	AXIS_EVENT,
	AXIS_TGID,
	AXIS_TID,
	AXIS_CPU,
	AXIS_MAX
};


struct profile_classes {
	/**
	 * This is only set if we're not classifying on event/count
	 * anyway - if we're classifying on event/count, then we'll
	 * already output the details of each class's event/count.
	 *
	 * It's only used when classifying by CPU, tgid etc. so the
	 * user can still see what perfctr event was used.
	 */
	std::string event;

	/// CPU info
	std::string cpuinfo;

	/// the actual classes
	std::vector<profile_class> v;

	/// the axis of the classes
	axis_types axis;

	/// the extra images to consider for this profile_classes
	extra_images extra_found_images;

	/// is this class set comparable with another?
	bool matches(profile_classes const & classes);
};


std::ostream & operator<<(std::ostream &, profile_sample_files const &);
std::ostream & operator<<(std::ostream &, profile_dep_set const &);
std::ostream & operator<<(std::ostream &, profile_set const &);
std::ostream & operator<<(std::ostream &, profile_template const &);
std::ostream & operator<<(std::ostream &, profile_class const &);
std::ostream & operator<<(std::ostream &, profile_classes const &);


/**
 * Take a list of sample filenames, and process them into a set of
 * classes containing profile_sets. Merging is done at this stage
 * as well as attaching dependent profiles to the main image.
 *
 * The classes correspond to the columns you'll get in opreport:
 * this can be a number of events, or different CPUs, etc.
 */
profile_classes const
arrange_profiles(std::list<std::string> const & files,
		 merge_option const & merge_by, extra_images const & extra);


/**
 * A set of sample files where the image binary to open
 * are all the same.
 */
struct image_set {
	/// this is main app image, *not* necessarily
	/// the one we need to open
	std::string app_image;

	/// the sample files
	std::list<profile_sample_files> files;
};

typedef std::list<image_set> image_group_set;

/**
 * All sample files where the binary image to open is
 * the same.
 *
 * This is the "inverse" to some degree of profile_set.
 * For example, here we might have image = "/lib/libc.so",
 * with groups being the profile classifications
 * tgid:404, tgid:301, etc.
 *
 * Within each group there's a number of image_sets.
 * All the sample files listed within the image_sets
 * are still for /lib/libc.so, but they may have
 * different app_image values, e.g. /bin/bash.
 * We need to keep track of the app_image values to
 * make opreport give the right info in the "app"
 * column.
 */
struct inverted_profile {
	inverted_profile() : error(image_ok) {}
	/// the image to open
	std::string image;

	/// an error found in reading the image
	mutable image_error error;

	/// all sample files with data for the above image
	std::vector<image_group_set> groups;
};


/**
 * Invert the profile set. For opreport -l, opannotate etc.,
 * processing the profile_classes directly is slow, because
 * we end up opening BFDs multiple times (for each class,
 * dependent images etc.). This function returns an inverted
 * set of sample files, where the primary sort is on the binary
 * image to open.
 *
 * Thus each element in the returned list is for exactly one
 * binary file that we're going to bfd_openr(). Attached to that
 * is the actual sample files we need to process for that binary
 * file. In order to get the output right, these have to be
 * marked with the profile class they're from (hence the groups
 * vector), and the app image that owned the sample file, if
 * applicable (hence image_set).
 */
std::list<inverted_profile> const
invert_profiles(profile_classes const & classes);

#endif /* !ARRANGE_PROFILES_H */