Devel::Events::Filter::Size - Add L<Devel::Size> info to event data.


Devel-Events-Filter-Size documentation Contained in the Devel-Events-Filter-Size distribution.

Index


Code Index:

NAME

Top

Devel::Events::Filter::Size - Add Devel::Size info to event data.

SYNOPSIS

Top

	my $f = Devel::Events::Filter::Size->new(
		handler => $h,
		fields => [qw/foo bar gorch/], # calculate the size of these fields
	);

	# OR

	my $f = Devel::Events::Filter::Size->new(
		handler => $h,
		fields => "object", # just one field
	);

DESCRIPTION

Top

This class uses Devel::Size and optionally Devel::Size::Report to provide size information for data found inside events.

Typical usage would be to apply it to the object field in conjunction with Devel::Events::Objects.

ATTRIBUTES

Top

fields

The fields whose size to check.

Can be a single string, or an array reference.

When undefined all fields will be computed.

one_field

This parameter controls the placement of the results (top level, or under the sizes field).

It defaults to true when fields is a scalar, and false in any other situation.

no_total

When true, total_size in Devel::Size will not be used.

Defaults to false.

no_report

When true, Devel::Size::Report will not be used.

Defaults to true.

METHODS

Top

filter_event

When is_one_field returns a true value, this method will add a size, and optionally a total_size and size_report field to the event. Otherwise it will add several of these to the sizes field, keyed by the refaddr of the value.

Only reference types will have their sizes computed.

is_one_field

Internal method. Used by filter_event

get_field

Returns the fields whose sizes need computing. This is either all fields if fields is undef, or the specified fields.

get_fields

Returns only one field. Used when is_one_field is true.

calculate_sizes

Return an entry with the size, total_size and size_report results.

calculate_size

See size in Devel::Size

calculate_total_size

Optionally uses total_size in Devel::Size, depending on the value of no_total.

calculate_size_report

Optionally loads Devel::Size::Report and uses uses report_size in Devel::Size::Report, depending on the value of no_report.

SEE ALSO

Top

Devel::Events, Devel::Size, Devel::Events::Filter

AUTHOR

Top

Yuval Kogman <nothingmuch@woobling.org>

COPYRIGHT & LICENSE

Top


Devel-Events-Filter-Size documentation Contained in the Devel-Events-Filter-Size distribution.

#!/usr/bin/perl

package Devel::Events::Filter::Size;
use Moose;

with qw/Devel::Events::Filter/;

our $VERSION = "0.03";

use Devel::Size ();
#use Devel::Size::Report (); # it breaks
use Scalar::Util qw/refaddr reftype/;

has fields => (
	isa => "Any",
	is  => "ro",
);

has one_field => (
	isa => "Bool",
	is  => "ro",
	lazy    => 1,
	default => sub {
		my $self = shift;
		defined $self->fields and not ref $self->fields;
	},
);

has no_total => (
	isa => "Bool",
	is  => "rw",
);

has no_report => (
	isa => "Bool",
	is  => "rw",
	default => 1,
);

sub filter_event {
	my ( $self, @event ) = @_;
	my ( $type, @data ) = @event;

	if ( $self->is_one_field(@event) ) {
		my $field = $self->get_field(@event);

		my $ref = { @data }->{ $field };

		return ( $type, $self->calculate_sizes($ref), @data );
	} else {
		my @fields = $self->get_fields(@event);

		my %sizes;
		my %fields = map { $_ => [] } @fields;

		my @data_copy = @data;

		while ( @data_copy ) {
			my ( $key, $value ) = splice( @data_copy, 0, 2 );
			push @{ $fields{$key} }, $value if exists $fields{$key};
		}

		foreach my $field ( @fields ) {
			foreach my $ref ( grep { ref } @{ $fields{$field} ||=[] } ) {
				push @{ $sizes{$field} }, {
					refaddr => refaddr($ref),
					$self->calculate_sizes($ref)
				};
			}
		}

		return (
			$type,
			sizes => \%sizes,
			@data,
		);
	}
}

sub is_one_field {
	my ( $self, @event ) = @_;
	$self->one_field;
}

sub get_fields {
	my ( $self, @args ) = @_;

	my $fields = $self->fields;

	if ( not ref $fields ) {
		if ( defined $fields ) {
			return $fields;
		} else {
			my ( $type, @data ) = @args;
			my ( $i, %seen );
			return ( grep { !$seen{$_}++ } grep { ++$i % 2 == 1 } @data ); # even fields
		}
	} else {
		if ( reftype $fields eq 'ARRAY' ) {
			return @$fields;
		} elsif ( reftype $fields eq 'CODE' ) {
			$self->$fields(@args);
		} else {
			die "Uknown type for field spec: $fields";
		}
	}
}

sub get_field {
	my ( $self, @args ) = @_;
	( $self->get_fields(@args) )[0];
}

sub calculate_sizes {
	my ( $self, $ref ) = @_;

	return (
		$self->calculate_size($ref),
 		$self->calculate_total_size($ref),
		$self->calculate_size_report($ref),
	);
}

sub calculate_size {
	my ( $self, $ref ) = @_;
	return ( size => Devel::Size::size($ref) );
}

sub calculate_total_size {
	my ( $self, $ref ) = @_;
	return if $self->no_total;
	return ( total_size => Devel::Size::total_size($ref) );
}

sub calculate_size_report {
	my ( $self, $ref ) = @_;
	return if $self->no_report;
	require Devel::Size::Report; # only use it if necessary, since it breaks for some people.
	return ( size_report => Devel::Size::Report::report_size($ref) );
}

__PACKAGE__;

__END__