[google-appengine] Re: About a heavy CPU demanding app

2009-09-10 Thread David Given

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Rodrigo wrote:
[...]
 I read all documentation I could, including the FAQ, but I still do
 not know: is it possible to have cron jobs whose execution times
 exceed 30 minutes?

You can't have any request, cron job or otherwise, whose execution time
exceeds 30 *seconds*. And that's wall clock time, not CPU time.

- --
David Given
d...@cowlark.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkqpPC8ACgkQf9E0noFvlzjZhQCgs4PitHLIVeoCzzYHRQxrUE/0
rRUAoNFEerbnObpmW++jFvnHfjnIlkEF
=3uD6
-END PGP SIGNATURE-

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---



[appengine-java] Startup takes forever

2009-09-08 Thread David Given

If I make a request to my app, and (I assume) AppEngine decides it needs 
to start up a new servlet instance for me, then warming up the server 
can take about 5000ms. Is this normal?

For example, the first two items in my log for a request will be:

09-08 12:57AM 30.917 [standard notification of incoming request]
09-08 12:57AM 35.344 
com.google.appengine.repackaged.com.google.common.base.FinalizableReferenceQueue$SystemLoader
 
loadFinalizer: Not allowed to access system class loader.

Note the five second difference between the two timestamps. This all 
happens before my app has even started running any code. As this only 
happens the first time, it's not really a problem, but does cause nasty 
red warning banners in my logs.

Possibly related, the first time I do a database request in one of these 
new servers, I'm getting the following scary backtrace. Everything 
*works* --- it's just a warning. Can I safely ignore it or is this a 
symptom of something wrong with my code?

09-08 12:57AM 35.361
com.google.appengine.repackaged.com.google.common.base.FinalizableReferenceQueue
 
init: Failed to start reference finalizer thread. Reference cleanup 
will only occur when new references are created.
java.lang.reflect.InvocationTargetException
at 
com.google.appengine.runtime.Request.process-5d48060cebaffe54(Request.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:40)
at 
com.google.appengine.repackaged.com.google.common.base.FinalizableReferenceQueue.init(FinalizableReferenceQueue.java:124)
at 
com.google.appengine.repackaged.com.google.common.labs.misc.InterningPools$WeakInterningPool.clinit(InterningPools.java:104)
at 
com.google.appengine.repackaged.com.google.common.labs.misc.InterningPools.newWeakInterningPool(InterningPools.java:48)
at 
com.google.appengine.repackaged.com.google.io.protocol.ProtocolSupport.clinit(ProtocolSupport.java:55)
at 
com.google.apphosting.api.DatastorePb$GetRequest.freeze(DatastorePb.java:7233)
at 
com.google.apphosting.api.DatastorePb$GetRequest$1.init(DatastorePb.java:7177)
at 
com.google.apphosting.api.DatastorePb$GetRequest.clinit(DatastorePb.java:7174)
at 
com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:90)
at 
com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:69)
at 
com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:57)
at 
com.cowlark.stellation2.server.db.GAEPersistenceInterface.atomicallyModify(GAEPersistenceInterface.java:130)
at 
com.cowlark.stellation2.server.db.GAEPersistenceInterface.lock(GAEPersistenceInterface.java:160)
at com.cowlark.stellation2.server.db.ServerDB.lock(ServerDB.java:110)
at 
com.cowlark.stellation2.server.RPCServiceImpl.ping(RPCServiceImpl.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:40)
at 
com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:527)
at 
com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:166)
at 
com.google.gwt.user.server.rpc.RemoteServiceServlet.doPost(RemoteServiceServlet.java:86)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:713)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at 
org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at 
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
at 
com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
at 
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
at 
com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at 
org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
at 
org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at 
org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at 
org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at 
org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at 
com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:237)
at 

[google-appengine] Re: Text based RPG

2009-09-08 Thread David Given

Brandon N. Wirtz wrote:
 You could build one of these... You'd go broke running it.  A MUD is always
 running.. It handles multiple threads and not only accepts requests but
 sends them to the user.. 

I actually *am* building something like one of these (using Java).

The biggest problem I've got is that GAE has no synchronisation 
mechanisms. None. There are transactions, but as they only work on 
single entities they're useless. This means that it's very hard to run 
game logic that needs to synchronously touch the global database.

To work round this I've implemented my own semaphore backed by the 
datastore; it's extremely nasty but does actually work. I then read the 
entire game database out of a blob in a single entity into RAM, run the 
game logic, write the database back again, and release the semaphore. 
That is also extremely nasty but it does all actually work. (My game's 
actually intended to be run on a standalone server, not GAE, but the 
persistence layers are all abstracted out to let me host on GAE for 
development purposes.) It'll congest rather badly but by the time 
congestion becomes an issue I should have a more suitable server.

Performance isn't bad; I'm usually getting request times of about 500ms 
when the server's hot. That breaks down to:

startup: anything from 10 to 5000ms
db load: 50ms
game logic:  50ms
build client update: 50ms (varies according to the size of the update)
db save: 100ms

Startup time is very strange. Sometimes it's practically nil, usually 
it's 100ms or so, and if the server's not hot it something takes many 
seconds (together with weird warnings about failing to start the 
finalisation thread). It's all out of my control --- it happens before 
the app starts.

Note that the cheapest part of the whole process is actually running the 
game logic! Most of the time most requests take 0ms, as nothing will 
have actually happened since the last request...

 GAE no process can run for more than a few seconds, so you'd have to use
 some polling tricks on the client to ask what happened and have a chron job
 run the main thread every few seconds...

I'm running the game logic asynchronously on-demand. After all, you only 
need to change things when someone's looking! This works beautifully, 
but if it's been a couple of days since the last request it can take a 
while; I'm planning to use a cron job to update the server every half 
hour or so to avoid this.

If you're writing a text-based game things will be both easier and 
harder. Easier, in that you don't have to do all the complex database 
synchronisation between the client and the server that I'm doing, and 
harder, because the game logic itself will be more complex and the 
client will need to poll much more frequently. (I can get away with a 
poll every ten minutes or so. A MUD can't.)

-- 
┌─── dg@cowlark.com ─ http://www.cowlark.com ─
│
│ They laughed at Newton. They laughed at Einstein. Of course, they
│ also laughed at Bozo the Clown. --- Carl Sagan

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---



[google-appengine] Re: Text based RPG

2009-09-08 Thread David Given

Nick Johnson (Google) wrote:
[...]
 Not true - Transactions can encompass entire entity groups. With the 
 correct entity group configuration, you could perform updates on local 
 areas of the map transactionally.

Is it possible to directly access entities in a group other than the 
root one? I was under the impression not (but I could well be wrong).

And I'm afraid it still wouldn't help --- I'd still need synchronisation 
between different groups when dealing with multiple areas on the map; 
and AppEngine's transactions are optimistic rather than blocking, which 
are no use to me.

In addition the overhead to performing a single database access appears 
to be so high that it's *much* faster to read and write the entire 
database in two accesses than it is to read parts of it using multiple 
queries! Although that may change as the database size grows.

-- 
┌─── dg@cowlark.com ─ http://www.cowlark.com ─
│
│ They laughed at Newton. They laughed at Einstein. Of course, they
│ also laughed at Bozo the Clown. --- Carl Sagan

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---



[google-appengine] Re: 30 Max simultaneous requests (maxThreads)?

2009-09-08 Thread David Given

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Adligo wrote:
[...]
 I mentioned is stored as a Session Attribute.  I assume that the app
 engine must be
 keeping the Session in a location that can be accessed by all
 threads.

I'm afraid not!

The *only* mechanism for communicating between requests is, AFAIK (and
if I'm wrong someone please correct me), memcache or the datastore. Any
request may be hosted in any servlet on any JVM on any machine in any
datacentre in any continent, and you can't rely on any two requests
running in the same place. (Or on the moon in the Google moonbase, but
given the latency that would be unlikely.) AppEngine is perfectly
entitled to run your code anywhere it feels like, although it's probably
going to run it close to the data.

 Otherwise how
 could anyone maintain any sort or security on the server side (most
 Jaas HttpFilters I have seen store the Subject[User] as a Session
 Attribute, including 2 that I wrote by hand for custom requirements
 and Spring security) ?

AppEngine does implement servlet sessions, but it's just a wrapper
around the datastore --- it will automatically save your session objects
and reload them for you. I don't believe it's defined when this happens,
though, so you probably can't change properties in one session and rely
on being able to see them change in another in real time.

Personally, I find it easiest if I just forget everything I ever knew
about servlets and start again from scratch when dealing with AppEngine.
It's sufficiently strange not to be able to take anything for granted.
(People here are most likely already tired of my rants about not being
able to synchronise between threads...)

- --
┌─── dg@cowlark.com ─ http://www.cowlark.com ─
│
│ People who think they know everything really annoy those of us who
│ know we don't. --- Bjarne Stroustrup
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iD8DBQFKprdKf9E0noFvlzgRAu3bAJ9/hEJSHlsaluusBljVRZyz/QF4HQCguPKw
2kt1/NVlqrU/T84idi6h11I=
=3mR2
-END PGP SIGNATURE-

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---



[appengine-java] Re: Can't make logging work

2009-08-23 Thread David Given

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

rick wrote:
 Did you try changing level to FINEST  in your logging.properties
 file  ?

Yes, that did it. Thanks very much!

(And it would be dead handy if the App Engine documentation could
mention this --- it is the only form of debugging available...)

- --
┌─── dg@cowlark.com ─ http://www.cowlark.com ─
│
│ People who think they know everything really annoy those of us who
│ know we don't. --- Bjarne Stroustrup
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iD8DBQFKkYP/f9E0noFvlzgRArgKAJ94eRBZ9BhaovPJjK46aC96GulDQQCgss+2
64Pi73XX/yK4z/vdstoBazo=
=coWh
-END PGP SIGNATURE-

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine for Java group.
To post to this group, send email to google-appengine-java@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en
-~--~~~~--~~--~--~---



[appengine-java] Can't make logging work

2009-08-22 Thread David Given

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Yes, another dumb question.

I am totally unable to make logging work on deployed apps. I've followed
the instructions rigorously, but nothing ever shows up in the 'Logging'
section of the Administration console.

I'm using the following helper class:

public class Log
{
private static final Logger _log =
Logger.getLogger(RPCServiceImpl.class.getName());

public static void log(String s, Object... o)
{
long now = new Date().getTime() % 100L;

s = now + :  + String.format(s, o);

_log.info(s);
System.out.println(s);
}
}

...and then calling it with 'Log.log(Hello, world!)' or equivalent.
Note that I'm both calling Logger.info() *and* writing to stdout ---
nothing ever shows up.

I have the standard logging.properties, my appengine-web.xml file is
pointing at it, and as far as I know everything's set up correctly. I
just never see anything. What am I missing here?

- --
┌─── dg@cowlark.com ─ http://www.cowlark.com ─
│
│ People who think they know everything really annoy those of us who
│ know we don't. --- Bjarne Stroustrup
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iD8DBQFKkIYpf9E0noFvlzgRAnnyAJ9u2piGART2oHxBoQGHGTUCqhPhkACgudQW
UbJAib2z2GU5/igd4cnuY3A=
=xksW
-END PGP SIGNATURE-

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine for Java group.
To post to this group, send email to google-appengine-java@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en
-~--~~~~--~~--~--~---



[google-appengine] Re: Serialised events

2009-08-04 Thread David Given

Adam wrote:
 David, I would suggest using a Request Repeater pattern rather than
 Task Queues. What you want to achieve might be difficult or impossible
 with Task Queues.
   

That's very cunning --- ta. I can use that.

However, I'm not sure it quite meets all my requirements. This is good 
for ensuring that the event queue gets flushed periodically, which I'm 
going to want to do, but I also want to flush the queue on-demand (so 
that I can quickly process any pending events while the user's actually 
logged in).

Traditionally I'd do this with a big lock around the event processing 
routine, but appengine can't do this. I could use transactions, but I'd 
have to process each event --- which will involve touching and updating 
multiple entities all over my database --- inside a transaction, and 
that's going to be hideously expensive should contention happen (I'll 
end up processing the same event multiple times!) due to the optimistic 
transactions.

There has to be a better way to do this!

-- 
David Given
d...@cowlark.com

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---



[google-appengine] [appengine-java] Serialised events

2009-08-03 Thread David Given

Hi,

I'm trying to write a game using AppEngine. As a result, I need some
mechanism for running the game AI.

I've considered various architectures and the approach that seems the
most workable is to have, in the datastore, a priority queue of events
based on timestamp. I post events to the queue, and then process them in
order whenever it's necessary to update the state of the game world.
Most of this isn't hard.

The problem is that I can't find any way of achieving the 'in order'
part of the problem. It's vitally important that the event processing
happens serially, or else I'll end up processing events out of order,
with hilarious consequences --- I would like my unit to pick up cargo
*before* it departs the current location, thanks very much!

Normally I'd achieve this by having a single thread do all the AI
processing, so the AI becomes intrinsically serialised. Naturally, this
isn't possible in AppEngine. The only other approach I can think of is
to put some kind of big lock around the AI processing routine, to ensure
that only one thread at a time handles events; but AppEngine doesn't
have that kind of lock. Transactions aren't suitable because they're not
blocking.

This must be a situation people have encountered before --- any 
suggestions as to the best way to achieve this sort of thing?

-- 
David Given
d...@cowlark.com

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Google App Engine group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~--~~~~--~~--~--~---