Skip Menu |

This queue is for tickets about the Moose CPAN distribution.

Report information
The Basics
Id: 130240
Status: open
Priority: 0/
Queue: Moose

People
Owner: Nobody in particular
Requestors: niels.de.carpenter [...] intl.att.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Moose performance issue in delete method of Native Hash traits
Date: Thu, 1 Aug 2019 14:39:58 +0000
To: "bug-Moose [...] rt.cpan.org" <bug-Moose [...] rt.cpan.org>
From: "De Carpenter, Niels" <niels.de.carpenter [...] intl.att.com>
Hi, We encountered a serious performance degradation when we upgraded from Moose 2.12.13 to 2.2011. The issue turned out to be cause by very bad performance of the delete method when using Native Hash traits. The issue is in "lib64/perl5/Moose/Meta/Method/Accessor/Native/Hash/delete.pm", specifically: # There are no new members so we don't need to coerce new values (none exist) # and we always want to check the new (empty) hash as a whole. sub _inline_coerce_new_values { '' } sub _check_new_members_only { 0 } This causes all objects in the hash to be checked when deleting a single entry from it. For very large hashes this has a serious performance impact. The comment that the new hash will be empty is wrong of course. Setting _check_new_members_only to 1 fixes the issue. A small script to reproduce the issue: #!/usr/bin/perl package TEST::Entry; use strict; use warnings FATAL => 'all'; use Moose; use namespace::autoclean; has 'name' => ( # To help identify what the data is while debugging is => 'ro', isa => 'Str', required => '1', ); has 'value' => ( is => 'ro', isa => 'Int', required => '1', ); __PACKAGE__->meta->make_immutable; 1; package TEST::HashRef; use strict; use warnings FATAL => 'all'; use Moose; use namespace::autoclean; has '_entries' => ( traits => ['Hash'], is => 'ro', isa => 'HashRef[TEST::Entry]', default => sub { {} }, handles => { keys => 'keys', add => 'set', get => 'get', exists => 'exists', del => 'delete', count => 'count', }, ); __PACKAGE__->meta->make_immutable; package main; use Time::HiRes qw(gettimeofday tv_interval); print "OK\n"; my $hash = TEST::HashRef->new(); test(100000); sub test { my $count = shift; my $string = sprintf("test-%s",$count); print "Running $string\n"; my $name; for (my $i=1; $i <= $count; $i++) { $name = sprintf("%s-%s",$string, $i); $hash->add( $name, TEST::Entry->new( { name => $name, value => '1' } ) ); } my $t0 = [gettimeofday]; $hash->del($name); my $e0 = tv_interval( $t0, [gettimeofday] ); my $cnt = $hash->count; printf( "$string delete of last entry took %s, there are now %d entries in hash\n", $e0,$cnt ); } 1; Regards, Niels de Carpentier DevOps Engineer Integrator Solutions - Systems and Tools Center of Excellence AT&T Global Business

Message body is not shown because it is too large.

Setting _check_new_members_only() to return true is not the right solution. The problem here is that we have no way of knowing what the overall type check for the attribute is looking for. For example, you could have a type that checks that there are at least 2 k/v pairs in the hash. If we don't check the constraint after the delete then you could obviously end up with an invalid value. I'm really not sure if there's a good way to fix this. The type constraint system doesn't have a way for us to figure out what the constraint does and whether it needs to be run after a delete. Off hand I also can't think of a great workaround for you either :(
Subject: RE: [rt.cpan.org #130240] Moose performance issue in delete method of Native Hash traits
Date: Thu, 29 Aug 2019 09:38:28 +0000
To: "bug-Moose [...] rt.cpan.org" <bug-Moose [...] rt.cpan.org>
From: "De Carpenter, Niels" <niels.de.carpenter [...] intl.att.com>
Hi Dave, I'm not sure I understand as this is just for the native hash trait, if you have a type that has a requirement for at least 2 k/v pairs in the hash it is not a Native hash anymore? If someone needs a special type with special constraints, _check_new_members_only() so be set to false as part of the definition for that type. (Or am I missing something??) Niels Show quoted text
-----Original Message----- From: Dave Rolsky via RT <bug-Moose@rt.cpan.org> Sent: Wednesday, August 28, 2019 10:36 AM To: De Carpenter, Niels <niels.de.carpenter@intl.att.com> Subject: [rt.cpan.org #130240] Moose performance issue in delete method of Native Hash traits <URL: https://urldefense.proofpoint.com/v2/url?u=https-3A__rt.cpan.org_Ticket_Display.html-3Fid-3D130240&d=DwIDaQ&c=LFYZ-o9_HUMeMTSQicvjIg&r=y731_v1E_MM5qFny7mhv3La88NQMmhodZIZ5ZXzIxxI&m=mIzMa6Xobm6maVRCmoAwNRcKuzM5GADI5YuJWfbGM9E&s=owdqPLHdOr0E13vATPmbLqkVjrjA-7hodBFsenJaKUY&e= > Setting _check_new_members_only() to return true is not the right solution. The problem here is that we have no way of knowing what the overall type check for the attribute is looking for. For example, you could have a type that checks that there are at least 2 k/v pairs in the hash. If we don't check the constraint after the delete then you could obviously end up with an invalid value. I'm really not sure if there's a good way to fix this. The type constraint system doesn't have a way for us to figure out what the constraint does and whether it needs to be run after a delete. Off hand I also can't think of a great workaround for you either :(
On 2019-08-29 08:06:31, niels.de.carpenter@intl.att.com wrote: Show quoted text
> Hi Dave, > > I'm not sure I understand as this is just for the native hash trait, > if you have a type that has a requirement for at least 2 k/v pairs in > the hash it is not a Native hash anymore? > If someone needs a special type with special constraints, > _check_new_members_only() so be set to false as part of the definition > for that type. (Or am I missing something??)
There's nothing about native hashes that requires the type to be "HashRef[`a`]" as opposed to "SubTypeOfHashRef[`a`]". And since we don't know what sort of checks that subtype might impose, we need to fire the entire check again when hash keys are deleted. It is entirely possible to define a subtype that required at least two keys. See the file I attached for an example.
Subject: native-with-subtype.pl
use v5.14; use strict; use warnings; package Foo; use Moose; use Moose::Util::TypeConstraints; has h => ( traits => ['Hash'], is => 'ro', isa => ( subtype 'HashRef', where { keys %{$_} >= 2 } ), default => sub { { foo => 2, bar => 4 } }, handles => { d => 'delete' }, ); package main; my $foo = Foo->new; $foo->d('foo'); # will not get here say for sort keys %{ $foo->h };
CC: Global MNS Systems Management RM <rm-mnsmanagement [...] intl.att.com>, "Bonte, Jari" <jari.bonte [...] intl.att.com>
Subject: RE: [rt.cpan.org #130240] Moose performance issue in delete method of Native Hash traits
Date: Thu, 29 Aug 2019 15:34:49 +0000
To: "bug-Moose [...] rt.cpan.org" <bug-Moose [...] rt.cpan.org>
From: "De Carpenter, Niels" <niels.de.carpenter [...] intl.att.com>
Hi Dave, The correct fix seems to be removing the definition of _check_new_members_only from "lib64/perl5/Moose/Meta/Method/Accessor/Native/Hash/delete.pm". The default version will handle both cases correctly and will run your script correctly while also solving the performance issue we were seeing. Niels Show quoted text
-----Original Message----- From: Dave Rolsky via RT <bug-Moose@rt.cpan.org> Sent: Thursday, August 29, 2019 3:40 PM To: De Carpenter, Niels <niels.de.carpenter@intl.att.com> Subject: [rt.cpan.org #130240] Moose performance issue in delete method of Native Hash traits <URL: https://urldefense.proofpoint.com/v2/url?u=https-3A__rt.cpan.org_Ticket_Display.html-3Fid-3D130240&d=DwIDaQ&c=LFYZ-o9_HUMeMTSQicvjIg&r=y731_v1E_MM5qFny7mhv3La88NQMmhodZIZ5ZXzIxxI&m=yLYlzcDPPOu1YQIdwoUaSgEbN3Ap4gij0QG3h0cDa2E&s=qPiyPbI6MXyTzK4CVIagHLCgYC5BxQzjzUoKkrYrIxg&e= > On 2019-08-29 08:06:31, niels.de.carpenter@intl.att.com wrote:
> Hi Dave, > > I'm not sure I understand as this is just for the native hash trait, > if you have a type that has a requirement for at least 2 k/v pairs in > the hash it is not a Native hash anymore? > If someone needs a special type with special constraints, > _check_new_members_only() so be set to false as part of the definition > for that type. (Or am I missing something??)
There's nothing about native hashes that requires the type to be "HashRef[`a`]" as opposed to "SubTypeOfHashRef[`a`]". And since we don't know what sort of checks that subtype might impose, we need to fire the entire check again when hash keys are deleted. It is entirely possible to define a subtype that required at least two keys. See the file I attached for an example.
On 2019-08-29 10:35:21, niels.de.carpenter@intl.att.com wrote: Show quoted text
> Hi Dave, > > The correct fix seems to be removing the definition of > _check_new_members_only from > "lib64/perl5/Moose/Meta/Method/Accessor/Native/Hash/delete.pm". > The default version will handle both cases correctly and will run your > script correctly while also solving the performance issue we were > seeing.
Yes, I think that is correct.