Alternate Profiler Proposal.

I spent all last week working through the issues of profiling and came up with an API
which is quite a bit different that the current API in the profile package.

I have checked in a new API in the altprofile package in the scratchpad.

I had the goal of coming up with a system which would make it easy to design
Profilability into any component (Note lower case ‘c’) without having to 
worry
about performance.  This is the same thinking that has gone into many logging systems
of late.  You add lots of debug logging to classes to make it easier to debug them at
a later date.  This profiling system follows the same line of thinking.

A component can be made profiler ready by implementing the Profilable interface.
This interface allows a component to expose a number of ProfilePoints as well as
tell the Profiler about any child Profilables.

ProfilePoints are extremely light weight when they are not connected to the Profiler.
So components can add ProfilePoints without having to worry about a performance hit
when the Profiler is not in use.

This implementation has been divided into 4 packages:

1) excalibur.altprofile: Defines the base interfaces and classes that most components
will directly make use of.

2) excalibur.altprofile.component: Defines a new ProfilerComponentManager which extends
the ExcaliburComponentManager and understands how to deal with Profilable components.

3) excalibur.altprofile.profiler:  This package contains the guts of the system.  It
defines a ProfilerManager which is where all the work of profiling an Avalon
application is handled.

4) excalibur.altprofile.profiler.gui: This package contains a reference implementation
of a simple GUI which enables you to browse and view the profiler aware elements of
an application.


The excalibur.altprofile.component package required that I make a couple changes to
the excalibur.component package to allow key classes to be extended.

So far, I have temporarily made the ResourceLimitingJdbcDataSource in the scratchpad
Profilable to make it easy to test things out.  The ProfileManager also includes
default profile points for monitoring the JVM memory.

Lets start out with a sample piece of code that will start up an application using
the ProfilerComponentManager and a Profiler GUI.  This code should be familiar to
anyone who has worked with the Excalibur ComponentManager:

------
                DefaultContext context = new DefaultContext();

                context.put("root", getServletContext().getRealPath("/"));
                context.makeReadOnly();
                
                DefaultConfigurationBuilder builder    = new 
DefaultConfigurationBuilder();
                Configuration             systemConfig = builder.build(configStream);
                
                DefaultLogKitManager logManager = new DefaultLogKitManager();
                Logger lmLogger = 
Hierarchy.getDefaultHierarchy().getLoggerFor("log-mgr");
                
lmLogger.setPriority(Priority.getPriorityForName(systemConfig.getAttribute("log", 
"INFO")));
                logManager.setLogger(lmLogger);
                logManager.configure(systemConfig.getChild("logkit"));
                
                
                // Set up the Profiler Manager
                DefaultProfilerManager profilerManager = new DefaultProfilerManager();
                
                profilerManager.enableLogging(new 
LogKitLogger(logManager.getLogger("pm")));
                profilerManager.configure(systemConfig.getChild("profiler"));
                profilerManager.initialize();
                
                // Set up the Role Manager
                Configuration               roleConfig = builder.build(roleStream);
                DefaultRoleManager          roles      = new DefaultRoleManager();

                roles.setLogger(logManager.getLogger("rm"));
                roles.configure(roleConfig);
                
                
                // Set up the Component Manager
                ProfilerComponentManager manager      = new ProfilerComponentManager();
                
                manager.setLogger(logManager.getLogger("cm"));
                manager.setLogKitManager(logManager);
                manager.contextualize(context);
                manager.setProfilerManager(profilerManager);
                manager.setRoleManager(roles);
                manager.configure(systemConfig.getChild("environment"));
                manager.initialize();
                
                // Set up the ProfilerFrame
                ProfilerFrame profilerFrame = new ProfilerFrame( profilerManager, 
"Nikko System Profiler" );
                profilerFrame.setVisible( true );
------

The differences are that this code creates a ProfilerManager and assigns it to the
ProfilerComponentManager using the setProfilerManager() method.  The code then
continues to create a ProfilerFrame passing the ProfilerManager to the constructor.
The ProfilerFrame is not required by the Profiler.  It is just a default way to view
the Profile data.

Without any other changes, your application should be able to be run using the above
code to launch the application.  But at this point none of the Profilable components
will be profiled because they have not been configured in the config file yet.

Components which implement Profilable are not added to the list of components to be
profiled by default.  To make them profilable, you must add a 
‘profilable’
attribute which gives them a profiler name.

Here is an example datasource configuration:
------
                <datasources>
                        <jdbc name="asp-service" profilable="jdbc-asp-service">
                                <pool-controller min="1" max="10"/>
                                <auto-commit>true</auto-commit>
                                <driver>org.postgresql.Driver</driver>
                                <dburl>jdbc:postgresql://host/asp_service</dburl>
                                <user>user</user>
                                <password>pwd</password>
                        </jdbc>
                </datasources>
------

Assuming the roles is configured to use a ResourceLimitingJdbcDataSource for the above
datasource, the profiler will now recognize the DataSource as a Profilable named
'jdbc-asp-service'.

An application can now request to be added as a listener of update events for any one
of 3 ProflilePoints published by the DataSource.

To make things work really nicely though,  we also need to configure the Profilable
using the profiler configuration.  It takes on the following format:

------
                <profiler>
                <profilables>
                <profilable name="profiler"
                                        description="Profiler">
                        <profile-point name="total-memory"
                                                   description="Total Memory">
                                <sample type="max" interval="1000" size="600"
                                                description="Maximum each second."/>
                                <sample type="max" interval="60000" size="1440"
                                                description="Maximum each minute."/>
                                <sample type="max" interval="3600000" size="720"
                                                description="Maximum each hour."/>
                        </profile-point>
                        
                        <profile-point name="free-memory"
                                                   description="Free Memory">
                                <sample type="min" interval="1000" size="600"
                                                description="Minimum each second."/>
                                <sample type="min" interval="60000" size="1440"
                                                description="Minimum each minute."/>
                                <sample type="min" interval="3600000" size="720"
                                                description="Minimum each hour."/>
                        </profile-point>
                        
                        <profile-point name="memory"
                                                   description="In-Use Memory">
                                <sample type="max" interval="1000" size="600"
                                                description="Maximum each second."/>
                                <sample type="max" interval="60000" size="1440"
                                                description="Maximum each minute."/>
                                <sample type="max" interval="3600000" size="720"
                                                description="Maximum each hour."/>
                        </profile-point>
                </profilable>
                
                <profilable name="jdbc-asp-service"
                                        description="ASP Service JDBC Pool">
                        <profile-point name="pool.new-poolables"
                                                   description="New Connections">
                                <sample type="ctr" interval="1000" size="600"
                                                description="Count / second."/>
                                <sample type="ctr" interval="60000" size="1440"
                                                description="Count / minute."/>
                                <sample type="ctr" interval="3600000" size="720"
                                                description="Count / hour."/>
                        </profile-point>
                        
                        <profile-point name="pool.size"
                                                   description="Open Connections">
                                <sample type="max" interval="1000" size="600"
                                                description="Maximum each second."/>
                                <sample type="max" interval="60000" size="1440"
                                                description="Maximum each minute."/>
                                <sample type="max" interval="3600000" size="720"
                                                description="Maximum each hour."/>
                        </profile-point>
                        
                        <profile-point name="pool.ready-size"
                                                   description="Available Connections">
                                <sample type="max" interval="1000" size="600"
                                                description="Maximum available each 
second."/>
                                <sample type="max" interval="60000" size="1440"
                                                description="Maximum available each 
minute."/>
                                <sample type="max" interval="3600000" size="720"
                                                description="Maximum available each 
hour."/>
                                
                                <sample type="min" interval="1000" size="600"
                                                description="Minimum available each 
second."/>
                                <sample type="min" interval="300000" size="288"
                                                description="Minimum available each 
minute."/>
                                <sample type="min" interval="3600000" size="720"
                                                description="Minimum available each 
hour."/>
                        </profile-point>
                </profilable>
        </profilables>
</profiler>
------

This example profiler configure configures two Profilables.  The first called 
"profiler"
configures the ProfilerManager.  The second, “jdbc-asp-service” 
configures our example
DataSource.

By default, ProfilePoints are purely pull based profiling objects.  In order to make 
the
profiling data available for a user to see at any time, the data must be collected and
stored into history.  This is done by defining one or more Samples for each Profile 
Point.

The system comes with two types of ProfilePoints.  The first, CounterProfilePoint, can 
be
used to profile the number of times an action takes place.  It exposes an increment()
method.  The second,  ValueProfilePoint, is used for profiling absolute values.  Things
like pool sizes, etc.  It exposes a setValue(int value) method.

CounterProfilePoints can be assigned samples of type “counter” 
(“ctr”).
ValueProfilePoints can be assigned samples of types “maximum” 
(“max”),
“minimum” (“min”), and “average” 
(“avg”).

Taking the “maximum” types sample as an example. It will monitor each 
call to setValue
for the ProfilePoint and store the maximum value in a particular sample period as the
value.  “minimum” stores the minimum value, and “average”, 
the average value for the
sample period.  The “counter” sample will store the number of times that 
increment()
was called on the ProfilePoint during the sample period.

The ProfilePoints which have samples visible will be viewable as graphs in real time
using the ProfilerFrame class.

Right now, this shouldn’t be too difficult to get set up.  But I get a example
application that will work out of the box very soon.

Wanted to get something up as soon as possible though because it looks like Marcus
has also been giving this a lot of thought.

Cheers, I am sure you will have some questions about how things work.  It is late
here now.  I should be able to answer them in the AM.

Cheers,
Leif



--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to