Skip to content

Fix contention due to lzycompute synchronised access in Metadata.normalize #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

jurisk
Copy link
Contributor

@jurisk jurisk commented Mar 7, 2017

Our performance traces show that Metadata.normalize uses a lazy val which leads to lzycompute synchronised access and lock contention.

scala.xml.MetaData$.key$lzycompute$1(NamespaceBinding, MetaData, ObjectRef, VolatileByteRef)	4,954	120,519,787,655
   scala.xml.MetaData$.key$1(NamespaceBinding, MetaData, ObjectRef, VolatileByteRef)	4,954	120,519,787,655
      scala.xml.MetaData$.iterate$1(MetaData, MetaData, Set, NamespaceBinding)	4,954	120,519,787,655
         scala.xml.MetaData$.iterate$1(MetaData, MetaData, Set, NamespaceBinding)	3,028	73,017,044,016
         scala.xml.MetaData$.normalize(MetaData, NamespaceBinding)	1,926	47,502,743,639
            scala.xml.Elem.<init>(String, String, MetaData, NamespaceBinding, boolean, Seq)	1,926	47,502,743,639
               scala.xml.Elem$.apply(String, String, MetaData, NamespaceBinding, boolean, Seq)	1,387	33,803,514,665

Replacing it with a def should resolve this, which this PR does.

@SethTisue
Copy link
Member

SethTisue commented Mar 7, 2017

(I don't know this code, but:) is getUniversalKey expensive? because now we might be computing it twice.

@t3hnar
Copy link

t3hnar commented Mar 7, 2017

@SethTisue true, so would be nice to have the code as close as possible to original but without synchronisation introduced by lazy val

@ashawley
Copy link
Member

ashawley commented Mar 8, 2017

Maybe just break up the conditional logic so that it can be a val?

      if (md eq Null) normalized_attribs
      else if (md.value eq null) iterate(md.next, normalized_attribs, set)
      else {
        val key = getUniversalKey(md, scope)
        if (set(key)) iterate(md.next, normalized_attribs, set)
        else md copy iterate(md.next, normalized_attribs, set + key)
      }

@jurisk
Copy link
Contributor Author

jurisk commented Mar 9, 2017

@SethTisue Good point.
@ashawley It's done as you've suggested.

ashawley added a commit that referenced this pull request Jun 7, 2017
Fix contention due to lzycompute synchronised access in
Metadata.normalize
@ashawley
Copy link
Member

ashawley commented Jun 7, 2017

Closed with 7ad0adc after rebase

@ashawley ashawley closed this Jun 7, 2017
@ashawley
Copy link
Member

ashawley commented Jun 7, 2017

Thanks for reporting this and for submitting the fix. With any luck, this will be released in 1.0.7 relatively soon.

@ashawley ashawley added this to the 1.1.0 milestone Oct 7, 2017
@ashawley ashawley mentioned this pull request Oct 9, 2017
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants