blob: a0f5014ceac5e8431221104c0759d9509da08ad8 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file declares the HeatMapSimulation class.
#ifndef SYZYGY_SIMULATE_HEAT_MAP_SIMULATION_H_
#define SYZYGY_SIMULATE_HEAT_MAP_SIMULATION_H_
#include <map>
#include "base/strings/string_piece.h"
#include "syzygy/core/json_file_writer.h"
#include "syzygy/simulate/simulation_event_handler.h"
#include "syzygy/trace/parse/parser.h"
namespace simulate {
// An implementation of SimulationEventHandler.
// HeatMapSimulation parses trace events, gathers the code blocks from them,
// and organizes those by the number of times each memory slice of a given
// size, in bytes, was called during a time slice of a given size,
// in microseconds.
//
// HeatMapSimulation simulation;
//
// simulation.set_time_slice_usecs(5);
// simulation.set_memory_slice_bytes(0x4000);
// simulation.OnProcessStarted(time, 0);
// simulation.OnFunctionEntry(times[0], 0, 5);
// simulation.OnFunctionEntry(times[1], 3, 200);
// simulation.SerializeToJSON(file, pretty_print);
//
// If the time slice size or the memory slice size are not set, the default
// values of 1 and 0x8000, respectively, are used.
class HeatMapSimulation : public SimulationEventHandler {
public:
class TimeSlice;
typedef block_graph::BlockGraph::Block Block;
typedef time_t TimeSliceId;
typedef std::map<TimeSliceId, TimeSlice> TimeMemoryMap;
typedef uint32_t MemorySliceId;
// The default time and memory slice sizes.
static const uint32_t kDefaultTimeSliceSize = 1;
static const uint32_t kDefaultMemorySliceSize = 0x8000;
// Construct a new HeatMapSimulation instance.
HeatMapSimulation();
// @name Accessors.
// @{
const TimeMemoryMap& time_memory_map() const { return time_memory_map_; }
uint32_t time_slice_usecs() const { return time_slice_usecs_; }
uint32_t memory_slice_bytes() const { return memory_slice_bytes_; }
TimeSliceId max_time_slice_usecs() const { return max_time_slice_usecs_; }
MemorySliceId max_memory_slice_bytes() const {
return max_memory_slice_bytes_;
}
// @}
// @name Mutators.
// @{
// Set the size of time slices used in the heat map.
// @param time_slice_usecs The size used, in microseconds.
void set_time_slice_usecs(uint32_t time_slice_usecs) {
DCHECK_LT(0u, time_slice_usecs);
time_slice_usecs_ = time_slice_usecs;
}
// Set the size of the memory slices used in the heat map.
// @param memory_slice_bytes The size used, in bytes.
void set_memory_slice_bytes(uint32_t memory_slice_bytes) {
DCHECK_LT(0u, memory_slice_bytes);
memory_slice_bytes_ = memory_slice_bytes;
}
// Set whether SerializeToJSON outputs information about each individual
// function in each time/memory block.
// @param print_output_individual_functions true for saving the names of each
// function, false otherwise.
void set_output_individual_functions(bool output_individual_functions) {
output_individual_functions_ = output_individual_functions;
}
// @}
// @name SimulationEventHandler implementation
// @{
// Sets the entry time of the trace file.
// @param time The startup time of the execution.
void OnProcessStarted(base::Time time, size_t default_page_size) override;
// Adds a group of code blocks corresponding to one function
// to time_memory_map_.
// @param time The entry time of the function.
// @param block_start The start start of the function.
// @param size The size of the function.
void OnFunctionEntry(base::Time time, const Block* block) override;
// Serializes the data to JSON.
// The serialization consists of a list containing a dictionary of each
// timestamp, and the total number of memory slices used, during that
// time slice, and of another list with dictionaries containing each
// separate memory slice, the number of times it was used, and a list
// of all the used functions and the number of times they were used in that
// memory slice in descending order. If output_individual_functions is true,
// then the list of function for each memory slice isn't printed. Example:
// {
// "time_slice_usecs": 1,
// "memory_slice_bytes": 32768,
// "time_slice_list": [
// {
// "timestamp": 31,
// "total_memory_slices": 1052,
// "memory_slice_list": [
// {
// "memory_slice": 4,
// "quantity": 978,
// "functions": [
// {
// "name": "_flush",
// "quantity": 561
// },
// {
// "name": "flsall",
// "quantity": 417
// }
// ]
// },
// {
// "memory_slice": 13,
// "quantity": 74,
// "functions": [
// {
// "name": "_RTC_Terminate",
// "quantity": 38
// },
// {
// "name": "_CrtDefaultAllocHook",
// "quantity": 36
// }
// ]
// }
// ]
// },
// {
// "timestamp": 33,
// "total_memory_slices": 105,
// "memory_slice_list": [
// {
// "memory_slice": 0,
// "quantity": 105,
// "functions": [
// {
// "name": "rand",
// "quantity": 105
// }
// ]
// }
// ]
// }
// ]
// }
// @param output the file to be written to.
// @param pretty_print enables or disables pretty printing.
// @returns true on success, false on failure.
bool SerializeToJSON(FILE* output, bool pretty_print);
// @}
protected:
// The size of each time block on the heat map, in microseconds.
uint32_t time_slice_usecs_;
// The size of each memory block on the heat map, in bytes.
uint32_t memory_slice_bytes_;
// A map which contains the density of each pair of time and memory slices.
// TODO(fixman): If there aren't many possible relative times,
// this will probably be better off as a vector.
TimeMemoryMap time_memory_map_;
// The time when the process was started. Used to convert absolute function
// entry times to relative times since start of process.
base::Time process_start_time_;
// The number of the last time and memory slice, respectively.
TimeSliceId max_time_slice_usecs_;
MemorySliceId max_memory_slice_bytes_;
// If set to true, SerializeToJSON outputs information about each function
// in each time/memory block. This gives more information and is useful
// for analysis, but may make the output files excessively big.
bool output_individual_functions_;
};
// Stores the respective memory slices of a particular time slice in a map.
class HeatMapSimulation::TimeSlice {
public:
typedef std::map<std::string, uint32_t> FunctionMap;
struct MemorySlice {
FunctionMap functions;
uint32_t total;
MemorySlice() : total(0) {
}
};
typedef std::map<MemorySliceId, MemorySlice> MemorySliceMap;
TimeSlice() : total_(0) {
}
// Add a quantity of bytes to a memory slice to the counter.
// @param slice The relative code block number.
// @param name The name of the function which uses the memory slice.
// @param num_bytes The value to be added, in bytes.
void AddSlice(MemorySliceId slice,
const base::StringPiece& name,
uint32_t num_bytes) {
slices_[slice].functions[name.as_string()] += num_bytes;
slices_[slice].total += num_bytes;
total_ += num_bytes;
}
// @name Accessors.
// @{
const MemorySliceMap& slices() const { return slices_; }
uint32_t total() const { return total_; }
// @}
// Serialize a FunctionMap to a JSON file, sorted by bytes occupied by
// each function.
// @param json_file The file where the functions will be serialized.
// @param functions The given functions.
// @returns true on success, false on failure.
static bool PrintJSONFunctions(core::JSONFileWriter& json_file,
const FunctionMap& functions);
protected:
// The slices that were accumulated at this time, and how many times
// they were called.
MemorySliceMap slices_;
// The total number of blocks that were called at this time.
uint32_t total_;
};
} // namespace simulate
#endif // SYZYGY_SIMULATE_HEAT_MAP_SIMULATION_H_