5 Replies Latest reply on Jan 29, 2002 6:43 PM by juha

    new code checked in

    squirest

      Hey Guys,

      Ok it took more than a couple of hours (as I first imagined) but I've committed my changes WRT capabilties and invokers. I tagged the pre-checkin tree in case there is a burning desire to back out of the changes.

      Running the performance testsuite yields interesting results. Initially I was more than a little pi$$ed at the numbers but I've figured it out now and it boils down to these two statements:

      If you are passing null for params and signature when calling server.invoke() then the new invokers are up to 50% slower.

      If you are passing non-null for params and signature when calling server.invoke() then the new invokers are up to 50% faster.

      Also, for DynamicMBeans the new invokers are *always* slower because interceptors were only ever added to standard MBeans in the old code. It's a neccesary evil and we're only talking about a few hundred extra milliseconds across a million invocations so I'm not losing sleep over it.

      We are still orders of magnitude faster than the RI but that's a dubious metric given that we are not feature-complete.

      There's still much to be done but working backwards through the invokation chain, starting at Providers, then MBeanAdapter etc etc, it's clearly signposted what's required.

      In the back of my head I'm thinking that once all reflection-based calls are routed through Providers we can go one step further - eliminating the DynamicMBean sugar so that the MBeanServer internals speak *Invocation objects directly to an interceptorChain head in the MBeanEntry (and an MBeanTarget that talks directly to Providers for StdMBeans). Whew.

      We've got testsuite issues which I'll talk about in another posting.

      Trev

        • 1. Re: new code checked in
          marc.fleury


          > If you are passing null for params and signature when
          > calling server.invoke() then the new invokers are up
          > to 50% slower.
          >
          > If you are passing non-null for params and signature
          > when calling server.invoke() then the new invokers
          > are up to 50% faster.

          Isn't there a way to fix that one?

          > Also, for DynamicMBeans the new invokers are *always*
          > slower because interceptors were only ever added to
          > standard MBeans in the old code. It's a neccesary
          > evil and we're only talking about a few hundred extra
          > milliseconds across a million invocations so I'm not
          > losing sleep over it.

          Yes that is more than ok, in general interceptors are not very expensive.

          > We are still orders of magnitude faster than the RI
          > but that's a dubious metric given that we are not
          > feature-complete.

          In fact I don't think the JMX server should be feature complete for fear of "bloating" all we need is the base and the right classloaders and repositories and the deployers to it and many of the services can then be pulled down.

          You should focus on the microkernel (the micro part of it) and then we pull the whole JMX compliant implementation with URLClassLoaders like we do JBoss.

          > There's still much to be done but working backwards
          > through the invokation chain, starting at Providers,
          > then MBeanAdapter etc etc, it's clearly signposted
          > what's required.

          I am thinking of providing a proxy generation service where you give interfaces, proxy implementation and invokers to the JMX node, we use these in the EJB invoker. It buys you transparent security and transaction propagation through any interface. There are other places where they will be useful namely the new XA pools stuff I think.

          > In the back of my head I'm thinking that once all
          > reflection-based calls are routed through Providers
          > we can go one step further - eliminating the
          > DynamicMBean sugar so that the MBeanServer internals
          > speak *Invocation objects directly to an
          > interceptorChain head in the MBeanEntry (and an
          > MBeanTarget that talks directly to Providers for
          > StdMBeans). Whew.
          >
          > We've got testsuite issues which I'll talk about in
          > another posting.
          >
          > Trev

          • 2. Re: new code checked in
            squirest



            > Isn't there a way to fix that one?

            Well, my perspective is that it's only slower when you are calling methods in MBeans that have a void argument list. So unless you want to incrementBlurdy() all the time it's not a big deal IMHO. We're talking about an extra 150 milliseconds across one hundred thousand invocations at worst.

            If you *really* need those milliseconds back then your biggest win will be a switch your managed resource to a DynamicMBean to avoid reflection (10X faster easily).

            > Yes that is more than ok, in general interceptors are
            > not very expensive.

            Well this may be an issue if Juha is thinking of putting an additional invocation chain between the XMBean and the target objects. If it becomes a problem of spurious interceptors we can code around it.

            In fact, the way that interceptors are inserted between the MBeanServerImpl and the MBean itself may be pointless.

            Per-MBean interceptors could be handled by allowing an XMBean to manage an interceptor chain between itself and the target object(s) (or a StandardMBeanAdapter).

            Interceptors that apply to *all* MBeans or to the usage of the MBeanServer (typically something like a SecurityInterceptor) might be better placed as wrappers to the MBeanServer instances returned by the MBeanServerFactory and instances passed in MBeanRegistration calls.

            > You should focus on the microkernel (the micro part
            > of it) and then we pull the whole JMX compliant
            > implementation with URLClassLoaders like we do JBoss.

            Well, I'm sure it's obvious to both you and Juha that ModelMBeans are a good way to crosscut extra features into a managed resource by setting specific operation targets in the Descriptor.

            However, I just realised that there's no reason why the descriptor can't also contain an OperationProvider supplied by the creator of the ModelMBeanInfo. And there's no reason why the OperationProvider has to use reflection if it's a custom one for a known, high-throughput method.

            The value of such a scheme really depends on how you intend on assembling target objects into a larger whole and how you plan on dispatching calls.

            > I am thinking of providing a proxy generation service
            > where you give interfaces, proxy implementation and
            > invokers to the JMX node, we use these in the EJB
            > invoker.

            There's some "issues" and opportunities with that sort of feature. The biggest issue is the cost of JDK1.3 proxies. I won't go into anything else 'cause the rest is just implementation details that'll quietly get sorted out.

            Trev

            • 3. Re: new code checked in

              >
              > Well this may be an issue if Juha is thinking of
              > putting an additional invocation chain between the
              > XMBean and the target objects. If it becomes a
              > problem of spurious interceptors we can code around
              > it.

              Hmm.. the way the code currently stands (or should, I'm not looking at it right now, and can't remember my code) is that there is only one invocation chain, and that is between the ModelMBean implementation and the managed resource (target object).

              The XMBean implements ModelMBean and extends MBeanInvoker (the ModelBase is bad class naming on my part, been meaning to change it to ModelMBeanInvoker). Therefore the MBeanServer directly invokes the ModelMBean (no interceptors there) and the ModelMBean invokes the target object through the interceptor stack.

              This is in order to retain the portability of an XMBean based component between JMX servers. The component in this case is not only the target object but also the accompanying interceptor stack functionality to go with it (for example, the persistence callbacks to store(), etc).

              > In fact, the way that interceptors are inserted
              > between the MBeanServerImpl and the MBean itself may
              > be pointless.

              Right. Today we have a "dual-mode" of
              server -> interceptors -> Standard MBean
              server -> ModelMBean -> interceptors -> target(s)

              However, as model mbeans can be used to represent any standard MBean we should move to using only the latter (as was discussed earlier).

              >
              > Per-MBean interceptors could be handled by allowing
              > an XMBean to manage an interceptor chain between
              > itself and the target object(s)

              and it does, although its somewhat unobvious from the code

              > Interceptors that apply to *all* MBeans or to the
              > usage of the MBeanServer (typically something like a
              > SecurityInterceptor) might be better placed as
              > wrappers to the MBeanServer instances returned by
              > the MBeanServerFactory and instances passed in
              > MBeanRegistration calls.

              Do we need this? My point of view is keep interceptors only between the Model MBean and target object. However, there could be either Per-MBean interceptors (that's what currently all interceptors are, instance per MBean) or shared interceptors. Shared interceptors can be implemented as MBeans and registered to the server. In the stack propagation the direct method call is in that case replaced with the MBeanServer invoke().

              Whether or not shared interceptors will be useful I don't know yet.


              > > You should focus on the microkernel (the micropart
              > > of it) and then we pull the whole JMX compliant
              > > implementation with URLClassLoaders like we do JBoss.

              Yes, agree with this. Have a bootstrap loader pull the MBeanServer and MLet service, and the MLet service pull all the other loaders and services.


              -- Juha

              • 4. Re: new code checked in
                marc.fleury


                > > Interceptors that apply to *all* MBeans or to the
                > > usage of the MBeanServer (typically something like
                > a
                > > SecurityInterceptor) might be better placed as
                > > wrappers to the MBeanServer instances returned by
                > > the MBeanServerFactory and instances passed in
                > > MBeanRegistration calls.
                >
                > Do we need this? My point of view is keep
                > interceptors only between the Model MBean and target
                > object. However, there could be either Per-MBean
                > interceptors (that's what currently all interceptors
                > are, instance per MBean) or shared interceptors.
                > Shared interceptors can be implemented as MBeans and
                > registered to the server. In the stack propagation
                > the direct method call is in that case replaced with
                > the MBeanServer invoke().

                If we follow the idea that at some point the EJBs themselves will be the ModelMBean with the interceptor stack with the target MBean being the "ContainerInvoker" at the end of the interceptor stack, then you see that having the generic security essentially breaks the security model for Scott's stuff. Keep security as an interceptor keep it in the stack in between model MBean and target. Having the model will enable us to provide dynamic reconfiguration of the EJB stack in a smart way I like it and all the stack must be present (say reconfigure the security interceptor that way to deploy a new security proxy for JAAS)...

                > Whether or not shared interceptors will be useful I
                > don't know yet.

                That is another question the statelessness of the interceptor is real but I feel that keeping the configuration of the plugins that go with it at the container stack level is a little bit more straightforward.

                The option is to put all contextual information in the Invocation object itself, set at the "gate" of the stack (first interceptor). Today in many interceptors we do a container.getThis().doThat() and essentially getThis is configured statically from the XML today (plugins and their stuff) all this can move to the Invocation so you say
                invocation.getThis().doThat() instead. you "container" is purely stateless. That being said I think that thinking of the container stack as "one" is a simpler thought.
                Small point at this point.


                > Yes, agree with this. Have a bootstrap loader pull
                > the MBeanServer and MLet service, and the MLet
                > service pull all the other loaders and services.

                Your MLet must be a UCL extension otherwise you break visibility ok?

                marcf
                >
                > -- Juha

                • 5. Re: new code checked in

                  > Your MLet must be a UCL extension otherwise you break
                  > visibility ok?

                  hmm?

                  I have to extend some CL (UCL?) so it can be added to the ServiceLib? Doesn't the ServiceLib take just any ClassLoader instance?

                  visibility? huh?

                  extending won't be prob though... but not there yet, will see it when there.