Pages

Showing posts with label engine. Show all posts
Showing posts with label engine. Show all posts

Wednesday, March 12, 2014

Google App Engine helps MAG Interactive handle explosive growth of word game Ruzzle

Today we hear from Daniel Hasselberg, co-founder and chief executive officer of mobile game development company, MAG Interactive, based in Stockholm, Sweden. MAG Interactive produces some of the most popular games in the world, including Ruzzle, which has more than 45 million players in 142 different countries.



When we launched our word game Ruzzle in 2012, we had no idea it would become an international sensation almost overnight. We initially promoted the game only to our family and friends, but within two weeks of our launch, Ruzzle was the No.1 game on the Swedish App Store.



I believe if we hadn’t used Google App Engine to build the backend of Ruzzle, we wouldn’t have been able to scale fast enough with our own servers, which would have killed the app in the marketplace. There were about a million downloads of Ruzzle per month in the Nordic region, Holland, Spain and Italy through 2012. As we refined the game’s social integration through channels like Facebook and Twitter, we grew rapidly in Italy and the United States. In 2013, Ruzzle became the No. 1 game download on Google Play and the App Store in Italy, Sweden, the United States and many other countries.



Things were especially crazy at the end of last year. We were seeing about 700,000 new players each day from December 2012 through January 2013. We added 20 million users in a single month! It was incredible to see App Engine scale – and just keep on working – as we grew from about 5 million players to 25 million players in just a few weeks.



Our decision to use App Engine as the platform for Ruzzle and our new game, QuizCross, was strategic. Some of us at MAG Interactive helped develop the server platform for one of the most popular music download services in the Nordic region, so we knew about the challenges of having to scale quickly. While we didn’t anticipate Ruzzle’s popularity, we did recognize even before creating the game that we could face scaling problems if we were successful. So we decided from day one to use a cloud solution.



We looked at Amazon’s platform but preferred Google’s approach to cloud solutions. Google’s scalability was an important factor in our decision, but we also appreciated the company’s transparent pricing. The more efficient we became with App Engine, the less we paid.



The Google Cloud Platform team has been great to work with, as well. They are very supportive and appreciate our feedback. The technical support experts at Google are amazing, too – very hands-on. They know the platform extremely well and can help us work through any challenge.



We’re also using Google BigQuery for business intelligence. We track millions of events in the game every day so we know what users are doing – or not doing – and how we should improve the experience. We really like that we can throw enormous amounts of data at BigQuery, and it still performs. It only takes a few seconds to get results, and there are no scaling issues. It’s also easy to use. We have just one data analyst doing all the work with BigQuery but could probably use more people. If there are a few brilliant data mining experts out there who can imagine a future in Stockholm, please give us a call!



One thing we’ve learned from our BigQuery analysis is that the more users play Ruzzle, the more they improve their skills. New players typically find about 18 words in the two-minute time frame they’re given. After they play 100 games, they can find about 50 words, on average. I think that tracking player improvement is what keeps people playing and has helped to make Ruzzle so popular.



BigQuery offers our company a lot of insight into the use of our games and how we can improve them. We’re looking forward to expanding our relationship with Google as App Engine and Cloud Platform evolves.



-Contributed by Daniel Hasselberg, CEO, MAG Interactive
Read More..

Tuesday, March 11, 2014

10 things you probably didnt know about App Engine

What could be better than nine nifty tips and tricks about App Engine? Why, ten of course. As weve been participating in the discussion groups, weve noticed that some features of App Engine often go unnoticed so weve come up with just under eleven fun facts which might just change the way that you develop your app. Without further ado, bring on the first tip:

1. App Versions are strings, not numbers

Although most of the examples show the version field in app.yaml and appengine-web.xml as a number, thats just a matter of convention. App versions can be any string thats allowed in a URL. For example, you could call your versions "live" and "dev", and they would be accessible at "live.latest.yourapp.appspot.com" and "dev.latest.yourapp.appspot.com".

2. You can have multiple versions of your app running simultaneously

As we alluded to in point 1, App Engine permits you to deploy multiple versions of your app and have them running side-by-side. All the versions share the samedatastore and memcache, but they run in separate instances and have different URLs. Your live version always serves off yourapp.appspot.com as well as any domains you have mapped, but all your apps versions are accessible at version.latest.yourapp.appspot.com. Multiple versions are particularly useful for testing a new release in a production environment, on real data, before making it available to all your users.

Something thats less known is that the different app versions dont even have to have the same runtime! Its perfectly fine to have one version of an app using the Java runtime and another version of the same app using the Python runtime.

3. The Java runtime supports any language that compiles to Java bytecode

Its called the Java runtime, but in fact theres nothing stopping you from writing your App Engine app in any other language that compiles to JVM bytecode. In fact, there are already people writing App Engine apps in JRuby, Groovy, Scala, Rhino (a JavaScript interpreter), Quercus (a PHP interpreter/compiler), and even Jython! Our community has shared notes on what theyve found to work and not work on the following wiki page.

4. The IN and != operators generate multiple datastore queries under the hood

The IN and != operators in the Python runtime are actually implemented in the SDK and translate to multiple queries under the hood.

For example, the query "SELECT * FROM People WHERE name IN (Bob, Jane)" gets translated into two queries, equivalent to running "SELECT * FROM People WHERE name = Bob" and "SELECT * FROM People WHERE name = Jane" and merging the results. Combining multiple disjunctions multiplies the number of queries needed, so the query "SELECT * FROM People WHERE name IN (Bob, Jane) AND age != 25" generates a total of four queries, for each of the possible conditions (age less than or greater than 25, and name is Bob or Jane), then merges them together into a single result set.

The upshot of this is that you should avoid using excessively large disjunctions. If youre using an inequality query, for example, and you expect only a small number of records to exactly match the condition (e.g. in the above example, you know very few people will have an age of exactly 25), it may be more efficient to execute the query without the inequality filter and exclude any returned records that dont match it yourself.

5. You can batch put, get and delete operations for efficiency

Every time you make a datastore request, such as a query or a get() operation, your app has to send the request off to the datastore, which processes the request and sends back a response. This request-response cycle takes time, and if youre doing a lot of operations one after the other, this can add up to a substantial delay in how long your users have to wait to see a result.

Fortunately, theres an easy way to reduce the number of round trips: batch operations. The db.put(), db.get(), and db.delete() functions all accept lists in addition to their more usual singular invocation. When passed a list, they perform the operation on all the items in the list in a singledatastore round trip and they are executed in parallel, saving you a lot of time. For example, take a look at this common pattern:

for entity in MyModel.all().filter("color =",
old_favorite).fetch(100):
entity.color = new_favorite
entity.put()

Doing the update this way requires one datastore round trip for the query, plus one additional round trip for each updated entity - for a total of up to 101 round trips! In comparison, take a look at this example:

updated = []
for entity in MyModel.all().filter("color =",
old_favorite).fetch(100):
entity.color = new_favorite
updated.append(entity)
db.put(updated)

By adding two lines, weve reduced the number of round trips required from 101 to just 2!

6. Datastore performance doesnt depend on how many entities you have

Many people ask about how the datastore will perform once theyve inserted 100,000, or a million, or ten million entities. One of the datastores major strengths is that its performance is totally independent of the number of entities your app has. So much so, in fact, that every entity for every App Engine app is stored in a singleBigTable table! Further, when it comes to queries, all the queries that you can execute natively (with the notable exception of those involving IN and != operators - see above) have equivalent execution cost: The cost of running a query is proportional to the number of results returned by that query.

7. The time it takes to build an index isnt entirely dependent on its size

When adding a new index to your app on App Engine, it sometimes takes a significant amount of time to build. People often inquire about this, citing the amount of data they have compared to the time taken. However, requests to build new indexes are actually added to a queue of indexes that need to be built, and processed by a centralized system that builds indexes for all App Engine apps. At peak times, there may be other index building jobs ahead of yours in the queue, delaying when we can start building your index.

8. The value for Stored Data is updated once a day

Once a day, we run a task to recalculate the Stored Data figure for your app based on your actual datastore usage at that time. In the intervening period, we update the figure with an estimate of your usage so we can give you immediate feedback on changes in your usage. This explains why many people have observed that after deleting a large number of entities, theirdatastore usage remains at previous levels for a while. For billing purposes, only the authoritative number is used, naturally.

9. The order that handlers in app.yaml, web.xml, and appengine-web.xml are specified in matters

One of the more common and subtle mistakes people make when configuring their app is to forget that handlers in the application configuration files are processed in order, from top to bottom. For example, when installing remote_api, many people do the following:

handlers:
- url: /.*
script: request.py

- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin

The above looks fine at first glance, but because handlers are processed in order, the handler for request.py is encountered first, and all requests - even those for remote_api - get handled by request.py. Since request.py doesnt know about remote_api, it returns a 404 Not Found error. The solution is simple: Make sure that the catchall handler comes after all other handlers.

The same is true for the Java runtime, with the additional constraint that all the static file handlers in appengine-web.xml are processed before any of the dynamic handlers in web.xml.

10. You dont need to construct GQL strings by hand

One anti-pattern that comes up a lot looks similar to this:

q = db.GqlQuery("SELECT * FROM People "
"WHERE first_name = " + first_name
+ " AND last_name = " + last_name + "")

As well as opening up your code to injection vulnerabilities, this practice introduces escaping issues (what if a user has an apostrophe in their name?) and potentially, encoding issues. Fortunately,GqlQuery has built in support for parameter substitution, a common technique for avoiding the need to substitute in strings in the first place. Using parameter substitution, the above query can be rephrased like this:

q = db.GqlQuery("SELECT * FROM People "
"WHERE first_name = :1 "
"AND last_name = :2", first_name, last_name)

GqlQuery also supports using named instead of numbered parameters, and passing a dictionary as an argument:

q = db.GqlQuery("SELECT * FROM People "
"WHERE first_name = :first_name "
"AND last_name = :last_name",
first_name=first_name, last_name=last_name)

Aside from cleaning up your code, this also allows for some neat optimizations. If youre going to execute the same query multiple times with different values, you can useGqlQuery .bind() to rebind the values of the parameters for each query. This is faster than constructing a new query each time, because the query only has to be parsed once:

q = db.GqlQuery("SELECT * FROM People "
"WHERE first_name = :first_name "
"AND last_name = :last_name")
for first, last in people:
q.bind(first, last)
person = q.get()
print person


Java is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries.

Read More..

Monday, March 10, 2014

App Engine 1 7 7 Released


3 weeks following our last release, the App Engine team is happy to announce 1.7.7.  We plan to deliver our Google I/O release next month.  




Outbound sockets moved to Preview

Outbound sockets is now in preview in this release for Java and Python.  With outbound sockets, billing-enabled App Engine applications can now make outbound connections with TCP or UDP sockets.  This allows developers to build applications that weren’t previously possible on App Engine, such as IMAP or DNS clients.




In the Python runtime, we’ve added support for the Python SSL Library, so you can now open secure connections to remote services such as Apple’s Push Notification service. Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections.




Java 7 runtime upgraded to General Availability


The App Engine team is committed to quickly releasing features to General Availability.  You may recall we announced that the Java 7 runtime was in preview just 2 months ago.  Since then we have seen 200% adoption week over week, and today are happy to announce the General Availability of the runtime.  




In order to help developers move over, all app deployments initiated using the new 1.7.7 SDK will use Java 7 unless you explicitly opt out with a command line flag.  In the near future, we plan to automatically update all existing Java 6 applications to Java 7.  Most applications shouldn’t be affected by this change, but we encourage you to start testing your application in advance.  For more compatibility information, we suggest that you check out the Java SE 7 and JDK 7 Compatibility notes.




Google App Engine Maven Plugin


The Google App Engine Maven plugin has been updated to support new goals: now you can directly enhance Datanucleus classes, and generate Google Cloud Endpoints service discovery and client libraries.




Improving the developer experience - goodbye $2.10!


We’re happy to announce that billing-enabled applications will no longer be required to spend a minimum of $2.10 per week. This means that you can enable billing for a free tier application and continue running within the free tier without concern that a spike in traffic will terminate serving (note that you can always specify a daily dollar budget). The minimum spend was originally intended to prevent abuse and ensure that we can offer a stable, reliable system with a free tier.  We have determined that we can continue to support the free tier, without relying on the minimum spend.  So, goodbye $2.10!




Cloud SDK Preview


In our continuing effort to make developers’ lives easier, we are happy to share with you a preview release of the Google Cloud SDK which includes everything from the App Engine SDKs for Java, Python or Go as well as all the tools needed to target Google Compute Engine, Google Cloud SQL, Google Cloud Storage and Google BigQuery in one easy-to-use package.  Please try it out; we are eager to hear your feedback.




A note on reliability improvements


A key benefit of running on a managed service like App Engine is the changes that occur behind the scenes that automatically improve the performance of your applications.  In just the past two months, we’ve made many such improvements:



  • Faster and more consistent deployments.  Many customers are seeing up to 10x reductions in time to deploy a new application version.



  • We have fully deployed an entirely new scheduler system which autoscales applications more smoothly and efficiently.





  • Admin console dashboard charts and current load/error reports have moved to a new, more reliable backend



  • The release version of App Engine is now visible in the Admin Console and in request logs



  • Several stability and scheduling improvements to Task Queue






The complete list of features and bug fixes for 1.7.7 can be found in our release notes. For App Engine coding questions and answers check us out on Stack Overflow, and for general discussion and feedback, find us on our Google Group.






- Posted by Chris Ramsdale, Product Manager









Read More..