mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-30 22:58:46 +00:00
Significantly reduce size of block_t
A `block_t` instance is allocated for each live block type in memory when executing a script or snippet of fish code. While many of the items in a `block_t` class are specific to a particular type of block, the overhead of `maybe_t<event_t>` that's unused except in the relatively extremely rare case of an event block is more significant than the rest, given that 88 out of the 216 bytes of a `block_t` are set aside for this field that is rarely used. This patch reorders the `block_t` members by order of decreasing alignment, bringing down the size to 208 bytes, then changes `maybe_t<event_t>` to `shared_ptr<event_t>` instead of allocating room for the event on the stack. This brings down the runtime memory size of a `block_t` to 136 bytes for a 37% reduction in size. I would like to investigate using inheritance and virtual methods to have a `block_t` only include the values that actually make sense for the block rather than always allocating some sort of storage for them and then only sometimes using it. In addition to further reducing the memory, I think this could also be a safer and saner approach overall, as it would make it very clear when and where we can expect each block_type_type_t-dependent member to be present and hold a value.
This commit is contained in:
parent
44c9c51841
commit
84b53b4cae
2 changed files with 25 additions and 18 deletions
|
@ -740,7 +740,7 @@ block_t block_t::if_block() { return block_t(block_type_t::if_block); }
|
||||||
|
|
||||||
block_t block_t::event_block(event_t evt) {
|
block_t block_t::event_block(event_t evt) {
|
||||||
block_t b{block_type_t::event};
|
block_t b{block_type_t::event};
|
||||||
b.event = std::move(evt);
|
b.event.reset(new event_t(std::move(evt)));
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
41
src/parser.h
41
src/parser.h
|
@ -38,7 +38,7 @@ inline bool event_block_list_blocks_type(const event_blockage_list_t &ebls) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types of blocks.
|
/// Types of blocks.
|
||||||
enum class block_type_t {
|
enum class block_type_t : uint16_t {
|
||||||
while_block, /// While loop block
|
while_block, /// While loop block
|
||||||
for_block, /// For loop block
|
for_block, /// For loop block
|
||||||
if_block, /// If block
|
if_block, /// If block
|
||||||
|
@ -63,40 +63,47 @@ enum class loop_status_t {
|
||||||
|
|
||||||
/// block_t represents a block of commands.
|
/// block_t represents a block of commands.
|
||||||
class block_t {
|
class block_t {
|
||||||
|
private:
|
||||||
/// Construct from a block type.
|
/// Construct from a block type.
|
||||||
explicit block_t(block_type_t t);
|
explicit block_t(block_type_t t);
|
||||||
|
|
||||||
/// Type of block.
|
|
||||||
const block_type_t block_type;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Name of file that created this block.
|
// If this is a function block, the function name. Otherwise empty.
|
||||||
filename_ref_t src_filename{};
|
wcstring function_name{};
|
||||||
/// Line number where this block was created.
|
|
||||||
int src_lineno{0};
|
|
||||||
/// Whether we should pop the environment variable stack when we're popped off of the block
|
|
||||||
/// stack.
|
|
||||||
bool wants_pop_env{false};
|
|
||||||
/// List of event blocks.
|
/// List of event blocks.
|
||||||
event_blockage_list_t event_blocks{};
|
event_blockage_list_t event_blocks{};
|
||||||
|
|
||||||
// If this is a function block, the function name and arguments.
|
// If this is a function block, the function args. Otherwise empty.
|
||||||
// Otherwise empty.
|
|
||||||
wcstring function_name{};
|
|
||||||
wcstring_list_t function_args{};
|
wcstring_list_t function_args{};
|
||||||
|
|
||||||
|
/// Name of file that created this block.
|
||||||
|
filename_ref_t src_filename{};
|
||||||
|
|
||||||
|
// If this is an event block, the event. Otherwise ignored.
|
||||||
|
std::shared_ptr<event_t> event;
|
||||||
|
|
||||||
// If this is a source block, the source'd file, interned.
|
// If this is a source block, the source'd file, interned.
|
||||||
// Otherwise nothing.
|
// Otherwise nothing.
|
||||||
filename_ref_t sourced_file{};
|
filename_ref_t sourced_file{};
|
||||||
|
|
||||||
// If this is an event block, the event. Otherwise ignored.
|
/// Line number where this block was created.
|
||||||
maybe_t<event_t> event;
|
int src_lineno{0};
|
||||||
|
|
||||||
block_type_t type() const { return this->block_type; }
|
private:
|
||||||
|
/// Type of block.
|
||||||
|
const block_type_t block_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Whether we should pop the environment variable stack when we're popped off of the block
|
||||||
|
/// stack.
|
||||||
|
bool wants_pop_env{false};
|
||||||
|
|
||||||
/// Description of the block, for debugging.
|
/// Description of the block, for debugging.
|
||||||
wcstring description() const;
|
wcstring description() const;
|
||||||
|
|
||||||
|
block_type_t type() const { return this->block_type; }
|
||||||
|
|
||||||
/// \return if we are a function call (with or without shadowing).
|
/// \return if we are a function call (with or without shadowing).
|
||||||
bool is_function_call() const {
|
bool is_function_call() const {
|
||||||
return type() == block_type_t::function_call ||
|
return type() == block_type_t::function_call ||
|
||||||
|
|
Loading…
Reference in a new issue