WWDC2001 Session 618
Transcript
Kind: captions
Language: en
good afternoon it's good to see so many
people here I've checked out of their
hotels looking for a nice cool dark
place to catch some rest before they
take their flight back to wherever it is
they came from have you guys caught all
the other web objects sessions this week
get some good sessions who cut who cuts
deep Haman's presentation come on Damon
and then we had James Dempsey's singing
right okay well are there any Canadians
in the room yeah well I'm not Canadian
I'm from New Orleans Louisiana and I'm
not gonna sing or play the guitar or
anything we're gonna talk about some
really interesting stuff about web
objects now that came up to me yesterday
and he said Fitz what is that makes web
objects the an application server better
than all the other application servers
out there I said how should I know Bob
you're the product manager thank you for
your jaded applause anyway we're going
to talk about making your web objects
applications faster we have a couple of
goals we're gonna find and eliminate
performance bottlenecks in your
components in your application in your
enterprise object model we're going to
talk about three areas we're going to
talk about the tools needed to identify
trouble spots including tools that ship
with web objects we're going to talk
about certain types of bottlenecks to
look for in your web objects application
and then we're going to talk about
certain techniques which you can use
from the get-go that will eliminate
bottlenecks we're going to talk about
when to do performance tuning do you do
it now do you do it later
do you wait till you finish your app do
you start from the beginning we're going
to talk about some tools that ship with
web objects that make things a lot
easier
playback low events whoa stats other
methods to measuring performance of your
app we're going to discuss specifically
web objects and uof techniques to
improve your performance there's a lot
of other techniques out there which
we're not going to focus on related to
programming and in general but those are
for definitely another session and last
when it's time to upgrade your hardware
when it's time to get more RAM in that
machine when it's time to get more
processors when it's time to
increase your processors fortunately
webobjects I'm sorry increase the number
of machines you have app servers
fortunately web objects makes it really
easy to add machines to your server farm
now I'm a big fan of Donald Knuth you
know I used to be a big law tech fan
about eight or nine years ago
every else should use lot tech you know
way back you know in the old days when
XML wasn't even the cool buzzword yet
premature optimization is the root of
all evil now I put this in here
specifically because that is one of the
things that I am most guilty of when I
sit down we get a design for application
we start coding and I just want
everything to be really pretty we've got
a nice clean slate I want it to be fast
I want to make sure I don't do anything
that is a performance bottleneck
unfortunately that's not the time nor
the place for doing that kind of work
you want to work the cords functional
stability you have a specification you
create your application you want to get
functionally stable before you start
optimizing things because you never know
when you're going to add or remove
functionality you may opt Imai something
that doesn't even wind up in your final
application you may optimize something
that is buried in a myriad of other
heavy-duty methods and it turns out that
it was just a waste of your time you
don't want to sacrifice good design and
maintainability for optimizing you don't
want you don't want to wind up loosing
everything into a single method that
that's three hundred and seventy five
thousand lines long just because it goes
ten milliseconds faster on your little
performance meter speed is not
everything optimization is about making
your application faster but making your
development time just as fast it's also
about maintainability another thing I'll
talk about is a big carpenter adage
which is measure twice cut once if you
know I usually cut my finger first but
you want to measure modify and then
measure again so create a controlled
environment this is really important can
create a controlled environment do a
measurement make a change that you think
might be an improvement run your control
test again with no other change in it
and then you can get conclusive in from
evidence as to what helps and what
hinders
our technology Fame works provides a
number of different very handy things to
help you
measure your performance well event
profiles methods in your components it's
extremely precise method for measuring
what parts in your application take more
time
well there's also whoa stats what stats
is a very very enlightening thing to
have on your application you could pull
that up and tell it a quick look on one
page what what methods I mean sorry what
components are faster what components
are slower you can see mean time you can
see in this photo at the slowest access
or the fastest access tells you a lot
about what your components are doing the
playback manager can simulate multiple
users you set an NS user default in the
command line run your application with
the recording enabled and then when you
quit the application then you can
playback this session with one user
simulate n use to simulate 200 users
hammering your application lastly and
one of my personal favorites is sequel
debugging we all know that AOF create
generates sequel to talk to your
database I'm really happy to say that I
haven't put a line of sequel in an
application since I started using web
objects and that was one of the things
that it really made my life hell before
I discovered this technology this shows
you exactly all the sequel that web
objects generates and sends to your
database as well as information about
what web objects gets back what objects
gets back commit messages it gets back
it says the beginning internal
transaction finishing internal
transaction will tell you how many rows
it gets back it'll tell you when it's
committed changes to your database so
before we get started measuring and
testing we need to come up with a test
environment so you want to have your
test environment mirror your deployment
environment if your deployment
environment is to Sun Enterprise 10
thousands with 64 processors and 4
terabytes of RAM you don't want to make
your test system an old g3 that you
found in the back closet with about 32
megabytes of RAM running you know
something completely different you want
to over the same operating system if
you're deploying on Solaris
test on Solaris if you're deploying on
Mac OS 10
test on Mac os10 don't switch and change
don't switch and modify and change your
environment and midstream
you want to try temp the mirror the
number and kinds of servers now this is
something that is is a little little
difficult to do especially for really
large scale deployments if you've got a
if you've got a half a million dollars
where the big iron you're running your
deployment on you obviously can't afford
that for your test environment however
what you want to do is try mirrored as
closely as possible try a particular
scaled-down test environment of your
deployment environment and lastly you
want to isolate the test environment
from your users you don't want to have
your test environment running in the
same segment of your land as your
production environment you don't want
them to share in the same database for
example and I've seen that I've seen
that happen where a test environment
used the same database as the production
environment you're not going to get you
have so many variables other than what
you're testing you're not going to get
any conclusive results at all now so
we've had we've got us a test
environment set up we've gone up and
bought no more hardware now we're gonna
travel webpages are important you have
an application with 20 30 40 100 pages
make a list of the pages what pages are
going to be frequented every time
someone comes into the app for example
your main page that's something you
should work at to make blisteringly fast
because first impressions are paramount
when a user comes in and they see your
applications front page takes half a
minute to load no matter how fast the
rest of the app is they're still gonna
be left with that initial thought like
god I got here and it took me half an
hour to get the first page established
acceptance criteria what you want to do
is decide what is acceptable an
acceptable speed for my application if
you decide that you want every page to
return in half a second well then work
to meet that goal if you want every page
to return in a minute and your users
will put up with that and not go
elsewhere well that's a goal to work for
too you might want to work on a big
query page so you have a query page that
returns thousands of objects or raw
roads as we'll discuss later on maybe
that should return in five seconds
there's certain cases where a longer
wait is acceptable
decide how many users you want to
support concurrently is this application
a small data entry app for a small
company where you're going to have 20 or
30 people working on it a week or is it
a large online store or an online
presence where you're going to have
hundreds of users hitting the app at the
same time determine what you want to
test for next create test cases which
exercise the important pages Chris is
going to give us a little demo of using
well playback and then checking with
most ads and more events to see with a
speed of certain pages so you might want
to create specific isolated cases for
certain pages that are critical to your
app ok now we're talking about preparing
your test cases enabling recording for
your application the whoa recording path
path so if you want you have your
application you've finished you finished
your feature complete you're ready to do
a little bit of optimization you set the
command-line argument well recording
path you set it to a directory in our
case we use temp /foo rec this is our
directory where web the web obvious
application will write out a series of
transactions requests in response at
which records you're visiting the app
manual executes a test case set up that
variable set up that NS user default in
your application launch the application
execute the text face case stop the
application now you can repeat this with
different directories for each for each
test case you can point the the wall
recording path at different directories
and say this test case is going to test
the big fetch page this is going to test
the main page this is going to test a
user simulated user walking through the
application finding something and then
going back to another part to purchase
something for example now when you run
your test cases so now that we've
enabled that user default we're going to
pull that off of the command line and
we're gonna run the app like we would
run it in deployment now there's certain
defaults that you're going to want to
enable and or disable when you run when
you deploy your application first is
whoa caching enable low caching enabled
allows which is which default to know is
what allows you to do rapid development
on your application it allows you to
make changes to your dot wide and your
dot HTML files save them and reload that
in your browser and see it immediately
by setting this to yes web objects knows
that it's safe to cache these templates
in memory so you'll get a small hit the
first time web object reads the
templates off the disk but it will cache
them next time it will just follow a
pointer a reference I'm sorry in memory
to retrieve that information low
debugging enabled you want to set that
to no especially most especially if you
use will application dot debug string
that's a great method to use you can put
tons of debugging print statements in
your application which you'll see in
your console and then when you deploy
kick this over to know and go your merry
way you'll want to see any of those
you'll still see log strings you still
see print lines and whatnot but it'll
turn those off for you last but not
least and it's something that I want to
say with a little bit of a caveat is low
allows current request handling that
defaults to know now with this enables
if you turn this on is multi-threading
in your application this can provide a
dramatic speed-up but I strongly
strongly encourage you to be familiar
with the caveats of multi-threaded
programming before you turn this on
in my experience multi-threading bugs
are extremely difficult to track down
and believe me it's something that you
don't want to don't wind up working with
if you're not familiar with
multi-threading programming for
programming so now that we've got all
that set up we're going to disable the
recording start more than one instance
if you're looking at a large deployment
start one instance if you're looking at
a small deployment whatever your test
environment is run the playback run one
playback concurrently to run one at a
time running serially let the system
achieve steady state now this is very
important you have to remember that your
application contains it's the contains
information contains methods that start
and stop a new session is created and it
lives for a certain period of time and
dies the session death and birth are
something that's very important to your
application because your application is
going to run all day 24/7
so what you want to do is let it reach a
point where sessions are expiring and
new sessions are being created so it'll
create a sort of a steady receive a sort
of a steady state so we've run our
application we've done our playback we
recording we've done our playback now
we're going to take a look and see what
kind of information we can find out
about this application first we're going
to look at a couple of the couple of
pages we have low stats and well events
set up now these are direct actions they
are out-of-the-box now disabled you need
to set a password for them to use them
at all which we've done in our sample
app and the low stats is something you
just go to at any point after you set
the app and it's going to give you this
aggregate data it's collected about your
application on a component level now a
component as we know can be as big as a
page as small as a character so they'll
give you information on all of those you
might want to pay attention to the the
page ones about want to potentially pay
attention to a certain sub component
that's taken a lot of time configure
event recording now event recording is
something you need to go in and turn on
there's several different buttons you
can set say these are the kind of events
I want you to gather information about
web objects can amass an incredible
amount of events in a second I don't
even remember what the number is maybe
and cue any one of the guys from
engineering can say but it's
blisteringly fast and has a very little
effect on your application so you go to
event setup say tell me what these
events are do your playback and then you
can come back and look at the wall event
display page to see sub transaction
times all the way down to the method
granular level now
for those of you who have been around
doing web objects work since the old
days when we use that other language
anyway there were tools available for
you called G prof G Mon you'd have to
build your app in profile mode you'd
have to run your application
you'd have to quit your application you
have to run it through another program
and you get this really nice information
that told you about this well that's
really great but this is something
that's something that you had to prepare
for it to sit out it was very
time-consuming this is something that
happens on the fly in the product out of
the box
so we've done that now we can use whoa
stats to find the pages that don't meet
our acceptance criteria maybe we found a
page that takes 10 seconds well let's
look into why what's taking so long in
that page is it a method that's very
expensive is it a fetch to the database
is it a multiple fetch to the database
well event display after you find out
what pages are giving you trouble can
tell you what methods in that page are
giving you trouble who's taking the most
time in your application you can
evaluate and you should evaluate the
times relative to the total time that
your application is running pay
attention to what is used the most if
you have a page that's hit once a day in
the corner and it's really expensive and
it takes 20 minutes you might not want
to dedicate resources to fixing that
page you may instead wants to dedicate
resources to pick the two making the
front page faster or the query that
everyone does now I'm going to ask Chris
miner senior consulting engineer with
Apple eye services to come up and give
us a demo about using wool recording and
playback Chris so we need the guest one
so we're gonna skip the recording
portion because we did that earlier but
just to show you what that looks like as
a result use the the world recording
path and we created this as a result of
going through our application in a
typical usage fashion we ended up with
this recording and inside here are a
number of files you can see the request
and response is making up transactions
so this only has a a transaction or
excuse me nine transactions in it and
then we'll just look at what one of the
contents of one of these and you may be
able to tell from that that it's a
typical HTTP request
it's just recording the request that
came in from the browser that the app
got and then afterwards it records the
response that sends out so that should
look a lot like an HTML page
so then I've already got this
application running actually it's this
one here sorry
and then from a command-line I'm just
going to start up our our playback where
it's going to read from that directory
send each of the requests to the
application and then compare the result
with what it gets back this time so we
can see up here that it's going along
doing some logging to show you that it's
actually hitting the app in this case we
only have one playback going and we have
only one application instance and down
here you can see the some of the results
and the information that's coming back
for us so you can see that it's got
perhaps the requests that will go
through 0 through 8 and then it starts
over so the next one it would be a new
session so each time it gets the initial
request again that's going to the main
page again and that's starting a new
session and then you can see it's the
transaction times let's stop that for a
second over here this is the comparison
of the bytes that it expected to get
versus the bytes that it actually did
get so that can in some respects you can
tell if there's a real problem with your
app maybe a defect of sorts if it's
returning back something wildly
different that might well be a an error
page something dramatically different
than what I've expected so let me start
that running again and go have a look at
the low stats information
so get the login pages mentioned before
by default this will come up if you
haven't set up your app to allow you to
log in here you can't there's an a
command line option for that it's kind
of a security feature and there's a lot
of information in this page we're only
interested today and part of it so I'll
just go down to that bit this happens to
be you can see here there's two major
sections of component action statistics
and the direct actions as you can see
there are no component actions and
that's because this app relies
exclusively on direct actions we see
here on the left the page names it
doesn't give you anything that's at a
subpage level in this view and then I'd
like to point out these minimum and
maximum times over here you can see that
it's not terribly obviously on this
Hardware because it's written fast but
on my laptop it showed a dramatically
different value for the Macs and for the
men I mean this one's still pretty large
but it just goes to show that maybe on
the first hit first time you hit the the
main direct action the default direct
action it might take a lot longer for
something to happen but then over time
this average is going to go lower and
lower and you can see there that the
0.01 versus the half a second
[Applause]
so another thing we should be able to
see in here are what we just saw there
is at our session timeouts very short I
think we set it to about 15 seconds just
to demonstrate this other feature which
is the current active sessions versus
the maximum so here we have a hundred
and sixty three sessions created but our
current active session this is only 68
it's likely to stay at 68 for a long
time it might fluctuate going up or down
one but it shows this apps essentially
being driven in a steady state which is
essentially what we want because
otherwise information we'd get about CPU
usage and information we get about RAM
usage would be pretty much irrelevant so
now go on to the well event display so
here's the event logging that fits
referred to we're just going to look at
component events
and then once you set up what events
you're interested in you can actually
display display those events in this
case we're going to just reset this to
get a fresh view so our playback is
still running so this information still
getting updated and you can see that for
the component events there's the the
pages and but it's also the sub page
components as well there's a different
sorting capabilities to show this these
events in different ways so we'll group
them by page and then we can see
something like Oh perhaps that the add
movie page takes what seems like an
awful long time for the number of calls
relative to anything else so if you were
gonna get some some sort of speed
increase you might look for something in
here on an app wide basis something else
that's worth noting is that if these
times per call are below what your
criteria is then you're pretty much done
so this just tells you you don't have
any performance tuning to do which is
pretty much the case in this application
but you can drill down in here and see
where the the cost of rendering a
component comes from so at the bottom of
things we see the WD footer costs pretty
much nothing so maybe I to turn my
attention to the WD table element if I
were going to look for a place to pick
up some speed
okay and that's it okay
all right thank you now we're going to
and now we've talked about ways of
measuring their performance of your
application we're going to talk about
techniques for improving your app the
speed of your application technique
specific to web objects and the
enterprise object framework now maybe we
could review this week we talked about
there were to enterprise object adapters
available there were the JDBC adapter
and the anyone else remember the nun
adapter now the nun adapter is extremely
fast there are absolutely zero round
trips to the database and however it's
not quite as useful as the JDBC adapter
we want to reduce trips the database COF
rights like as I said before this sequel
and sends it to the database and the
database sends back well data sometimes
AOF will not do will ask the database
for data in a not so intelligent manner
we might say it might repeatedly ask the
database for little bits of data that it
could have just asked for all at once so
to find out where these problems exist
we turn on the user default yo adapter
debug enable now for those of you who
use print statements in your application
to see what some value of something is
where some sort of where some sort of
value changes or where your you are and
the currently in the request response
loop you'll see a number of print
statements go by on your console when
you turn on yo at the after debug
enabled you are gonna see more stuff in
your console than you ever knew to do
with your gonna see when yo F first logs
in your database you're gonna see every
round-trip thereafter tons and tons and
tons of fun things to look through now
when you look at this at this
information that you have tells you
perhaps you'll see that there's multiple
round trips for your database for one
for one request response at loop maybe
you're only maybe you're fetching for
our example those of you who are
familiar with the movies database you
know I'm not creative enough to come up
with like you know like election results
and stuff like that so I grab the movie
database it ships it's in a Java
business logic examples you know it's
tried and true when I fetch movies
and then perhaps I navigate some of
these faults one at a time as each vault
fires it might make a separate trip to
the database and it's extremely
inefficient because we all know that
each round-trip to database is pretty
expensive so we're gonna talk about ways
that you can optimize that one is to use
batch faulting teleo after that when you
fire off one fault go get a whole bunch
more we're gonna use pre-fit we can use
prefetching teleo f when you fetch these
entities I want you to fetch these
relationships at the same time just
because we're gonna be using them pretty
soon we could use a shared editing
context this was a recent addition to
web objects last year fantastic people
were already doing this putting in
editing context in their application and
talking to it this is a really
intelligent editing context that has
relations to each editing context in the
session you could put reference data
into the shared editing context fetch it
when your application starts up and
never fetch it again
or well there's a little detail that
won't go too into right now but it will
refresh your data eventually so if you
have a will pop up containing all the
cities that your company may service or
I will pop up containing something like
all the products that in your product
line that's something that's doesn't
change or changes very infrequently it
might be a great candidate for shared
editing context make your app read-only
this is extremely fast if you have an
application a scenario for example where
you have a back-office application where
users enter data where they change data
where they delete data and then front
application for your users where they
just come and look at things it's sort
of a reference application you can
actually go ahead and put everything in
the shared editing context and your
application will rarely have to go back
to the database for anything not only is
extremely fast but it's extremely memory
efficient because you don't have all
these duplicate copies remember each
editing context that contains an object
has another copy of that object for very
good reason mind you but when there's
situations where you can avoid that you
sure they would want to last you want to
record a voice of a friend's data
certainly the shared editing context
takes care of that for us another thing
we can do is reduce the amount of data
that we get from the database you can
use raw rose for non object data and
very
fetches raro czar yeah as you'll see
there are big speed improvement on your
on just a standard fetch because they
fetch the information in to EOF just as
always the information stretch in the
database columns and rows put into a
dictionary but instead of taking the
next step in creating your enterprise
objects objects with the business logic
built into them you just get this raw
data
just straight attributes there's a cake
there's occasions where it's very
convenient to have that you stretch
limits or don't allow unrestricted
searches right now I have to say right
now that my favorite search in now there
is Google you know you go to that I find
obscure error messages I type the error
message into Google when it comes back
with a page with the answer on it you
know I mean anybody else does this cough
or something you know is anybody still
awake out there my goodness
shouldn't eat in that big big lunches it
only gives you you can search for the
word Apple and you get hundreds of
thousands of respond it'll say found
four bajillion pages and it's only going
to show you 200 incorrect that
encourages you as a user to refine your
search maybe you want to look for Apple
Computer Apple Computer G for Apple
Computer G for with a cinema display
maybe I'll optimize your programming
experience don't allow unrestricted
searches make the user make the user
enter some sort of criteria now this
isn't always necessary if you have a
company with 50 employees and they had
search on last name search on first name
sure let them hit return let them get
all 50 employees and surf around to the
heart's content to work for a big
company that has 200,000 employees this
might not work so well an unrestricted
search might allow them to fetch your
whole database at which point your DBA
is gonna come hunt you down and kill you
and then you're also going to run a
memory in your machine so now I'm gonna
go ahead and give you a little demo of
some of the that demo some of the things
that we we did here so let's see we
should have two different screens coming
up shortly
now those of you either of you have been
to the web object object sessions this
week you guys have probably seen some
really cool demos some really cool
graphics you saw XM elementary you know
we got movie mechanics you know I have
to confess when I finish writing this
demo yesterday at about 11:30 it looked
like you know w3c consortium around like
1994 you know a gray background with the
big jars across we handed all this stuff
over to Matt for like a lot of you know
Matt furling who really made this stuff
look great let's hear it for Matt so
okay so what I have here is an
applicants application called movie
mechanics which I've already cranked up
and done some fun stuff with so I'm
going to stop it for starters and yeah I
didn't even mean that and now we're
going to start the application again and
when it decides to start up there it
goes
we have a couple of different defaults
that I've set up one here in fact I
could probably still go ahead and take a
look at this thing here let's see
optimization like that right Association
targets yeah
anyone resize oh it's way down here
hiding right there we go
okay you'll see I'm said I got you
adapter debug enable - yes
I've got it set to Worldport 1729
because I'm hitting it from this machine
over here and then we'll auto open in
browser know I'm not a big fan of the
auto opening browser thing so let's go
back to where we were so the application
is launched here and you'll see it says
welcome application gives you this URL
and some other information and the first
thing it tells you here is connecting
with dictionary okay it's connected to
our database it began an internal
transactions fetched five rows okay now
the first example we're going to do here
is our shared editing context say it
showed me share it at it in context
example okay we're gonna go take a
shared editing context using objects
we'll share that in context versus using
objects that we're just going to
straight fetch from the database so as
you see we have those five objects so if
I click on this alright
you notice up here no change no change
didn't touch the database didn't do
anything funny so let's find out how
long that to it that took point oh three
seconds now tell you a little bit about
how this timers working okay I've
written some just some simple Java
timestamp methods in the awake of my
page component I put on one out of the
light better come back over here I put
on the page component in the awake
method I do a timestamp I get the
current time and I save that and then at
the very end of my opinion response they
have another component that merely takes
to the current time at that point and
then gets the Delta between that in the
start time and then squirrel's it away
for me to put in this little clock here
so now what we're gonna do is go ahead
and do a regular fetch you'll notice
touch the database five rows were
processed it's not a how long that took
it'll make a liar out I mean this is
actually happening didn't just hard code
these values so this machine there's a
really fast machine and like my laptop
in fact if I look out there I do see a
couple of titanium laptops yeah I'd like
one of those let's talk about what these
do
the shared editing context fetches the
date at the beginning at the beginning
of your application when your
application starts
round trip to the database it's way fast
and it's great for reference data the
regular fetch is just a plain old fetch
and it requires at the least a
round-trip to the database and as you
can see there's a lot faster shared
editing context again this is basically
following a point a reference and the
regular fetch talks the database so now
we move on to something a little more
interesting batch fetching and pre
faulting so let me see it can see that
clap or make a noise who's used the
batch fetching and prefault in here
that's falling in prefetching okay so
we're gonna have some people who already
know the answer to this right so we have
three ways of getting the state note we
do a regular fetch now the way this
component works is I'm fetching all
movies out of the movies database all 88
of them and then I'm iterating through
the movies and I'm touching the roles
relationship each movie has a role
indiana jones for example has harrison
for has the role of indiana jones in the
role of marion whatnot I'm triggering
that fault for each movie so integrating
pup pup pup pup pup triggering those
faults now we have a regular fetch which
it just goes through that does the fetch
and then triggers those false we have
batch faulting on which sets the the
batch faulting on the rolls relationship
to 25 so that tells us is that when you
fetch these bunch of movies and you
navigate to to this particular
relationship go ahead and get some extra
stuff while you're there you know you're
running to the grocery to pick up milk
pick up some butter you know suppose
it's stick of butter and loaf of milk
both a part of a bread and a gallon of
milk pick up some other stuff while
you're there because it's likely we're
going to need this and last but not
least prefetching which is a very
particular thing which says when we
fetch the movies I want you to prefetch
these certain attributes of the movies
while you're there okay so I don't we at
least three license regular fetch batch
faulting prefetching who thinks the
regular fetch is gonna be fastest anyone
next mark
who thinks batch faulting is going to be
the fastest comes a little racier anyone
think batch faulting you all know that
prefetch is at the bottom so it's the
fastest
I don't think free fetch is gonna be the
fastest all right okay so let's let's
see what's gonna happen here
regular fetch look at that oh my god
would you look at that every one of
those big lines that's begin from begin
internal transaction to commit internal
transaction the round trip to the
database now man I can't even that was a
lot of round trips the database look at
that 88 to be precise let's find out how
long that took that took 7.0 four
seconds now mind you on my laptop this
takes like 20 seconds match faulting
look at that now we saw we saw a good
number of transactions go by here but
they're a little different looking right
there you see here this is some
information I put in here whoa whoa it's
still going what's it doing hello
someone tell me get in this machine
let's see what that comes out to okay so
anyway here we have this this
transaction here that fetches in this
case 84 rows it fetches is a big or
select statement select select the role
where the movie ID is this or this or
this or this so it comes back with a
whole bunch more of these relationships
on the first shot prefetching boom right
back at you how many fetches was that to
now look at the difference from that a
regular fetch were your fault thing
you're doing multiple round trips with
Avis many many many round trips the
database 7 seconds here two point twenty
three seconds for batch faulting in
point 52 seconds for prefetching now
here's something that's a little that's
interesting about this some people out
there might be saying well she's of
course the first one slowest because
then you'd fetch the ball in and in
sleep in this component I'm in
validating all objects in my editing
context which pretty much wipes
everything clean and makes the AF do
everything all over again
so we'll try this again just to show you
that there's nothing funny going on here
it's actually going to the database
again each time it's gonna be a little
faster because certain things are
didn't happy and whatnot so batch
fetching two point forty seconds this
time and last but not least of
prefetching 39 seconds point 39 seconds
let's talk a little more about them
regular fetch one round tip to the
database for each vault fired can be
extremely inefficient very very
time-consuming batch faulting its
defining the relationship in question
now this is a difference between batch
faulting and prefetching batch faulting
you can define that programmatically or
an ill modeler per relationship you
define it once a neo modeler and your
applications use your model and they
just go their merry way and it just
happens to many relationships only you
can't do batch faulting on a to one
relationship this fetches again the next
n objects whenever a fault is fired so
for example in this demo we set batch
faulting across the roles relationship
to 25 so it fetches one it faults in one
relationship and it gets the next 25
last is prefetching it's used on a fresh
specification so you have to consciously
go in when you create a new fetch and
say I want you to prefetch these things
when I when you get the movie I want you
to prefetch the director and I want you
to prefetch the roles or and you can
prefetch multiple relationships
it adds only one round-trip to the
original fast fetch it it's very very
very fast so enough of that we'll move
on to probably another one of my
favorites raw rose now raw Rose and
objects I just kind of blew it I hit the
button already so what I'm selecting
here all the movie roles in database I
wanted something with more data
obviously I don't have that much data in
this database
the difference is seemingly small when
you have a small amount of data but when
you have a lot of data the difference is
really really big so okay I just fetched
the raw Rose inadvertently and let's
take a look and see what the time was on
that 0.08 seconds now I'm gonna fetch
the object objects now raw Rose fetches
the precious rose out of the database
every column in the row and in this case
I'm fetching every column in the row you
can write sequel and only fetch certain
columns if you wish you could fetch the
primary key and maybe the title of
something but in this case I've fetched
everything sort and gave me back a bunch
of dictionaries
objects I fetch the I fetched an
information in the database you get get
all attributes for each object and
they're wrapped in enterprise objects
and boom you have your enterprise
objects so let's see how fast that goes
point 13 seconds now we'll click it a
couple times here to sort of let things
uh normalize out and see what the
difference is the difference it's kind
of it depends you'll see different
speeds
but in the most part it tends to come up
to about 50% or so speed improvement
depending if you tweak out your raro
fetch you can see a really really huge
improvement now there is a fantastic
fantastic article that I used for
reference on this on stepwise written by
Malcolm Crawford and I think he's
sitting right there that tells you in
great great deal Thank You mouths yeah
there you go there you go Malcolm as we
all know has done us a number of good
services this week let's talk a little
more let's talk a little more about what
these do rah rah rah Rose don't
instantiate enterprise objects you just
get back dictionaries key value title
Indiana Jones director George Lucas it
was Lucas wasn't it music John Williams
okay it's very fast it doesn't have to
select all columns objects is just a
plain old fetch it creates objects for
all the EOS it fetches and it can be
slow for very large fetches especially
when you're dealing with tens of
thousands of objects so I'm gonna I'm
not gonna take a look at well events set
up right now but I will really quickly
see if I can hit on low stats and see
what it tells me about this application
of mine that I was running okay so here
we are we have be nice and share which
is my little shared editing context demo
with an average time it's that's
basically pretty fast because even the
non-shared part is only fetching a
little bit of data there's the venerable
main round trips
round trips is where we did the
different kinds of fetching batch
faulting and prefetching look at that
the max is 7.2 you see that that was the
FET that was a round trip where we went
and batch and we single faulted
everything in and last but not least raw
rose which was basically pretty fast cuz
again we're just fetching the object
single fetch as you can see we fetched
450 rolls still that was very fast and I
just kicked something over here and so
it was very fast because we just fat did
one round-trip to the database so so
that's buddy let's get back to the
slides now thank you okay
you know we I had to get a Star Trek
token but I'm not a big Star Trek
Voyager fan you know so I went with the
classic right lazy instantiation I took
a programming web objects to class at I
took a program about these two classes
that at Apple in fact it took
programming objects one but programming
web objects two was taught by Kyle
Christensen it was absolutely fantastic
teacher anyone had time for teacher oh
it was the greatest class I didn't fall
asleep once a I said something to me
that just absolutely killed me he said
when you're when you're programming he
says you want to cook your steak until
it's smoking and then ten seconds less
and I said Kyle what the hell does that
mean he said he says you want to wait to
the absolute last second to do something
if you don't have to do it don't do it
because it may turn out you know 20 feet
away from here you don't have to do it
use the lazy instantiation this is an
example here we have Shatner's ego which
is going to take a long time to get
because it's really big as we all know
so the first time it's called it checks
the sense this private instance variable
to say is this not if it's null it goes
ahead fetches it squirrel's it away in
the instance variable for the next time
someone comes through and then returns
it huge bonus it's a great little trick
to use back to EOF stuff subclass yo
generic record instead of via custom
object a generic record has a couple of
little tweaks to the cute it was a key
value coding the way it stores the
information for the attributes of your
EO it's blistering fast especially in
web objects v absolutely incredible what
they've done with this don't overwrite
now another thing that your generic
record does as well is by default
deferred fault is a deferred faulting or
shared faulting deferred faulting the
first fall thing is enabled now whenever
let's let's say we fetch a movie okay
and it has several attributes it has
roll it has a link to director woody
used to do in the old days back in the
1990's we used to create a fault for
each one of these attributes now if
you're now a movie you'd say it has ten
possible faults we fetch a thousand
movies okay so we've just had to create
a thousand movie objects plus ten
thousand fault objects now the generic
record by default creates one shared
fault for all for all these different
faults that's incredible speed up
because you don't have to create all
these additional objects even though the
fault objects were small next and this
well this one seemed a little bit
obviously but I've seen some people do
some weird stuff don't override value
for key key value coding one of my
greatest friends in the web objects
framework is a patented key value coding
as we all know and we know that self or
pets are evil as well don't override
that key value value for key and take
value for key are called
incredibly often in enterprise objects
in your whoa components and they're
optimized to to be as fast as possible
something you don't want to over
Ryde certainly if you're debugging you
want to put something in their print
statement but make sure you rip that
whole thing out when you're done we have
object specific stuff we can synchronize
bindings by hand we have synchronizes
variables with bindings which is still
nowhere near as long as add objects to
both sides of relationship with key
we have synchronizes variables with
bindings which in well component by
defaults returns true now this is one of
the things that really blew my mind when
someone explained it to me they said
when you synchronize when you go through
the request responsive if you put a
simple string in your page it's going to
print the title of a movie or or
something or you have your own sub
component let's say it's custom sub
component it takes in a name or
something we all know the request
response loop big fans of the request
response loop awake take valuation
request invoke action a pendant response
and sleep okay
those three middle ones take values
request invoke action dependent response
there's a lot of stuff going on there
and one of the things that goes on in
those three methods are variable
synchronization from component parent
component the child component what that
means is that take values gets call boom
synchronize pass pass the value into the
chocolate pull it back out do it again
invoke action pass it in and pull it out
do it again and append response pass it
in pull it out that's like six method
calls there if you have a sub component
that you're using everywhere say a
button bar component that just has some
buttons on it that you want to pull some
information down from the parent floor
say it's just a footer and we can talk
about and we'll talk about a way if he
was making that footer faster in a
moment and you just need a little bit of
information from the page you might want
to say look web objects don't
synchronize these variables for me but
instead I'm going to take care of it
myself and then in the appropriate
method of the three above and I
mentioned you can pull or push off that
value that you need now if you want to
talk even faster we could talk about
using stateless components now stateless
component whenever our components
instantiated you get a new component you
say you know page with name boom new
component you put a component into a
into a page when that page gets
instantiated that sub component boom
gets instantiated
if you say that components stateless web
objects knows that this
the component that's not going to change
based on session or based on something a
user's done it's a stateless component
it loads it up once and it reuses it
over and over and over again so if you
have 700 users on your website and you
have that little footer that is the big
legal disclaimer in it
make that stateless and you don't have
700 of those lying around you have one
not only is it faster but you use less
memory now in the end here is sort of
thrown a couple little misc
miscellaneous things some of which
aren't necessarily related to web
objects but session timeout Chris showed
you before we had our session timeout
set to 15 seconds you know that's pretty
extreme but you might want to see what
the typical user experiences in your
application when a session times out you
get that that memory is it can is
available to the garbage collector to be
picked up eventually so that that means
that when your session gets bigger
bigger bigger they can squish it back
down a little more
fetch outside the request response loop
if a loser logs in then you need to get
some data base on that user but you
don't need it right away in that first
page you might want to do a delayed
action to fetch that or to put it in
sleep or or somewhere outside that
somewhere somewhere safe to put it
outside this and the users not going to
be waiting in dextra database I'm a big
fan of getting someone else to do this
for me you can notice a market
improvement especially if you're just
using single attribute primary keys
which is what we all know and love with
the enterprise subjects framework
offload images and Static data to
another server if you've got an
application that's serving up I just
experienced this recently QuickTime VR
is 300 400 kilobyte DRS and you've got
200,000 of these things well you don't
want your same web server as your app
that's serving up your web app to be
serving up these images you might want
have an additional web server the arse
dot your company comm images that your
company comm have that serve up the
static images and the arse and sound
files and God knows what check your HTML
check the HTML this is wow this is like
really obvious to me but now but wasn't
obvious to me at the time I had a page
that we designed for this client of our
with all these nested tables and you
know and it looked just the way they
want it and I was like oh thank god
that's over with and then we hit the
page and it just took forever to render
it took forever this was back in like
you know years ago 1999 I think check
the HTML see if you can't optimize your
HTML see if it's actually compliant run
HTML run a linting program over it make
sure it's it's valid HTML remove
extraneous tables do as much as you can
with as little as you can
and last but not least there's just Java
there's Java performance tuning things
like optimize it or J probe I believe
optimize it is currently available on
Mac OS 10 now lastly but not leastly
we'll talk a little bit about what we
learned we talked about determining
where the bottlenecks line measure
modify measure remember again in a
controlled environment change only one
thing we talked about web objects and
EOF techniques we have batch faulting
prefetching we have synchronizing
bindings we're not synchronizing
bindings stateless components that sort
of thing general programming techniques
lazy instantiation upgrade your hardware
huge thing right here you know if if
you're running application and you're
hitting swap in a deployment environment
you're doomed there's nothing that you
can sit down and optimize and improve
that second that your machines were not
a rain'll
and oftentimes you'll discover that
hardware is a lot cheaper than developer
manpower so with that I want to let you
know that if you hurry up please don't
run the web objects lab is open for
another 20 minutes downstairs in room K
the only session left web objects track
is the feedback forum which is going to
start at 3:30 and there's your contact
information which ensures all new to you
you