[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

pp_mapwhile, pp_iter



Hello,

Given the similarity of foreach and map I think it's a good idea to
refactor the optimization code in pp_enteriter and pp_iter to
pp_mapstart and pp_mapwhile, so that mappings over integer ranges,
arrays (as opposed to lists), reversed arrays etc benefit from the
same performance gains as were introduced to foreach.

This would involve making a block context for mapstart, and clearing
it on the exit condition of mapwhile.


This in turn would allow us to implement Gurusamy Sarathy's
conjectured optimization to prevent copying in cases like:

	my @concatenated = map { @$_ } @aoa;

Where the output list is bigger than the input one.

This involves copying the input data from the stack into an array.

However, in order to prevent cases like this:

	my @same_size = map { ... always returns a single scalar ... } @foo;

from copying unnecessarily, the copying should happen only when it's
first needed, so that scalar mappings can continue to work pretty
much in place on the stack.

The condition for this copying to a separate list is the same:

	/* might need to make room back there first */
	if (items > PL_markstack_ptr[-1] - PL_markstack_ptr[-2]) {

Except that now mapwhile would have a loop context to use, and will
copy the remainder of PL_curstack to a new temporary array, putting
it in cx->blk_loop.state_u.ary.ary and resetting ary.ix.

Thus the map would "upgrade" itself from an iteration on the stack
into an iteration on a temporary array when it would currently start
extending and copying the stack.


Lastly, another related optimization enabled by giving map it's own
context would would involve creating a new block_map type for the
context union, which has a destination array pointer, so that

	@foo = map { ... } @bar

would write to @foo instead of the stack. This would enable
optimization of a very common case of map usage, in a way that would
also render the stack copying unnecessary.

The case of mapping where ary and dst are the same, like:

	@foo = map { ... } @foo

could be implemented by allocating new array storage for @foo, while
iterating over the previous one or by copying elements to/from the
stack, to ensure correctness.

Thoughts? Is there anything I'm missing?

-- 
  Yuval Kogman <nothingmuch@woobling.org>
http://nothingmuch.woobling.org  0xEBD27418

PGP signature


Follow-Ups from:
Nicholas Clark <nick@ccl4.org>

[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]