=rem #16428 optimize protobuf serializer for master

#16428 for master
Hmm, just trying it out:
~~~scala
case Some(clazz) =>
  val maybeCachedParsingMethod = parsingMethodBindingRef.get().get(clazz)
  if (maybeCachedParsingMethod.isDefined)
    maybeCachedParsingMethod.get.invoke(null, bytes).asInstanceOf[Message]
  else {
    @tailrec
    def cacheMethod(parsingMethod: Method): Method = {
      val parsingMethodBinding = parsingMethodBindingRef.get()
      parsingMethodBinding.get(clazz) match {
        case Some(otherCached) ⇒ otherCached
        case None ⇒
          val newParsingMethodBinding = parsingMethodBinding.updated(clazz, parsingMethod)
          if (parsingMethodBindingRef.compareAndSet(parsingMethodBinding, newParsingMethodBinding))
            parsingMethod
          else
            cacheMethod(parsingMethod)
      }
    }
    import ProtobufSerializer.ARRAY_OF_BYTE_ARRAY
    cacheMethod(clazz.getDeclaredMethod("parseFrom", ARRAY_OF_BYTE_ARRAY: _*))).invoke(null, bytes).asInstanceOf[Message]
  }
~~~
I can’t say that this has a disturbing amount of duplication, and it definitely has less cognitive overhead. And it also is extremely close to @hepin1989’s code :-)