“The sky is falling! The sky is falling! Computers won’t get any faster unless programmers learn to write parallel code!” squawked Chicken Licken.
Henny Penny clucked in agreement: “Worse, there is Cloud Computing on the horizon, and it requires programmers to write parallel AND distributed code!”
Musing on business intelligence, particularly using Pentaho. Also interests in software design, particularly in the open source community.
Sunday, June 13, 2010
Children of Prolog
Saturday, June 5, 2010
Trends in programming and Amdal's Law
Wednesday, June 2, 2010
Trends in programming
- isolation (the probability of isolated systems failing is independent. So processes need to be isolated.)
- concurrency (do you need to worry about how many concurrent processes can you support? You need at least two systems to make a non-stop system. Even a two computer system is concurrent. You can't avoid concurrency)
- failure detection (if you can't detect a failure, you can't fix it. the thing that crashed can be the thing that detects failures.)
- fault identification (You need to figure out why there was a failure if you want to fix it.)
- live code upgrade (Systems that should never stop, need live code upgrade)
- stable storage (no backups, implies multiple copies. must keep crash logs)
In short, the article is a progress report on a valid effort but suffers badly from agressive overselling of its significance, long before convincing results have been reached.
Monday, May 10, 2010
Gaelyk again
Saturday, March 20, 2010
Jeffrey Zeldman vs. Ed Bott
In one breath he said, “I’m not challenging the quality of the hardware and software improvements,” and then, in the very next breath, he criticized Microsoft’s “brilliant browser engineers” for “torturing the IE rendering engine every couple of years instead of putting it out of its misery.”This certainly seems damning. But it isn't quite true. Each of the quotes can be pulled from Zeldman's blog, IE9 Preview, but Bott's juxtaposition of Zeldman's words are downright deceptive. The two statements were separated by four paragraphs, so perhaps Bott quite understands what 'very next breath' means. Or more likely, Bott is being intentionally being misleading.
- html5
- SVG 1.1
- GPU rendering using Direct2D
- CSS3
- new JavaScript engine
- improving Acid3 (which did improve from 32 to 55)
- support for CSS3 selectors (which improved from passing 574/578 tests to a perfect 578/578)
Thursday, March 4, 2010
Making the case for Scala
Monday, March 1, 2010
David Pollak's Web Framework Manifesto
The best part of blogs is that is makes it possible for people with clear ideas, not just fame or access to money, to be published. David Pollak certainly falls within the category of clear thinking people, and his Web Framework Manifesto, from November 2006, is a great technical summary of what we all should expect of a web framework. It is fascinating to see the breadth of frameworks that he has examined.
Security figures predominantly in this manifesto. He states:
There should exist an orthogonal security layer such that objects that are not accessible to a user should never be returned in a query for the user and fields on an object that are not accessible should not be visible. The security and access control rules should be algebraic and demonstrable during a security audit. This means that neither the view nor the controller should have to test for access control. Objects and requests should be sanitized before they get to the “controller.”At first, this seems like Spring Security, but the algebraic caught my eye. I don't know what this means. A Google search found Beyond Separation of Duty: An Algebra for Specifying High-level Security Policies, but this seems quite theoretical at this point. In the IEEE Security & Privacy Journal, the article, A Metrics Framework to Drive Application Security Improvement, describes a more pragmatic, but still quantitative approach to security.
David then went on to create and act as benevolent dictator for life of the Liftweb framework, or just Lift. As a benevolent dictator, it is no surprise that the key ideas of the Web Framework Manifesto are all present in Lift.
Friday, February 12, 2010
Liftweb 1.1 and Google AppEngine
With only minor modifications, I have repeated Joe Kutner's installation of Liftweb on AppEngine. I'm running OS/X, so I started by using macports to install maven2. I saw that Java App-Engine was just updated to 1.3.1, so that was installed and I adjusted my APPENGINE_HOME and M2_HOME in .profile. The latest liftweb version is 1.1-M8, so I'll try that one.
Now that I know I have updated libraries, I generated a liftweb project with:
mvn archetype:generate -U -DarchetypeGroupId=net.liftweb -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=1.1-M8 -DremoteRepositories=http://scala-tools.org/repo-releases -DgroupId=com.folkertsfotografie. rlftest -DartifactId= rlftestRather than using -Dversion=1.0-SNAPSHOT, I entered a version of 1.1-M8 when prompted in maven. As usual, then next commands were cd rlftestl and a quick mvn jetty:run to see that http://localhost:8080/ was working. As an eclipse user, I added mvn eclipse:eclipse. So far, so good. The simple helloword application came up normally under the jetty installed with liftweb.
To integrate with AppEngine, I just added the boilerplate appengine-web.xml in my WEB-INF directory. The contents are:
<?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>rlftest> <version>3</version> <system-properties> <property name="in.gae.j" value="true" /> </system-properties> <sessions-enabled>true</sessions-enabled> <static-files> <exclude path="/**" /> </static-files></appengine-web-app>With that done, I built the war file with mvn package. To run that war file under AppEngine, just type
$APPENGINE_HOME/bin/dev_appserver.sh target/rlftest-1.1-M8. That also worked, I could see http://localhost:8080/. Finally, I published this to appsite with $APPENGINE_HOME/bin/appcfg.sh update target/rlftest-1.1-M8.
With that done, I browsed my AppEngine control panel and tested that the hello world application. It worked without a hitch. Now, I can get back to learning liftweb and Scala. It isn't at all clear to me how liftweb and datastore will work together, but I'll just have to burn that bridge when I get to it. So thanks Joe, you have been a great help getting me started with Lift.
Sunday, February 7, 2010
Google Analytics: integration with web apps.
Google Analytics is a powerful, free tool to gather information on events in the click streams of your website's visitors. I'm trying to develop a web application for photographers, starting with my wife's site, folkertsfotografie.com. I'm tracking progress on fotositeproject and the new webapp is running on GAE, Google App Engine. This is a rather Google-centric project. I'm using Picasa to hold image galleries. The RSS from Blogger, Picasa and flickr are being integrated using Google's Feed API via the jQuery library jGFeed. So when we wanted to add analytics, Google Analytics was on the top our our list.
I had hoped to develop with Grails, but it has proven to be too slow. This is a known issue, and both Google and SpringSource are working on speed ups. I switch to Gaelyk, a lighter Groovy framework for GAE, which is resulting in reasonable performance. I looked at GAE sites using other Java frameworks, and was surprised how much faster they are. However, GAE also has similar issues with Rails on jRuby, presumably for the same architectural reasons. GAE performance with Groovy is still an issue, but one that I trust will have a happy ending in the next few months. GAE does a lot of validating of included libraries on startup, which is probably a really good thing for security. I wonder if they can have some standard pre-verified jar files for groovy, jruby, grails, sitemesh and so on. When I want to use one of these jars, I agree to use the 'Google compatible version'. When I load my app, they check the MD5 hash to make sure that I am still using an unadulterated copy & they can just copy their jar image into my application's memory without the expensive validation. Can't we pay this price once when we load the app, not every time we start it up? There is still activity in the Grails community to develop GAE integration, so I can't believe that this issue will remain for long.
Returning to my original topic: Google Analytics requires adding some code snippets to the bottom of each tracked 'page' or in the event handlers for tracked events. In a MVC design, the code snippets must resign in the views. However, the URLs are tied to controllers, so the keys for each URL need to be managed by the controller. I had assumed that a quick search would find others who had discussed this topic. Surprisingly, this is not the case. I have written a page that will read a Picasa RSS feed and then show the album in Galleriffic, a terrific jQuery image gallery. I want to have URLs like /gallery/show/sarah2009, so I don't want to place 'the key' in a file like /album/show.gsp, since the controller don't even expose that URL to the user. I certainly want to track patrick2009 with a different code that campingTripSpring2007, even if they both use the same view. So for each controller, I need a map of the view, the model, Google Analytics keys to use. This isn't quite model data, since the model should only have 'domain' data, which in this cased is information about the albums, media feeds, images, models and clients. It seems that only the controller is in a position to address this.
Wednesday, February 3, 2010
REST and application evolution
REST turns out to be the key to allowing software to be upgraded without breaking applications. The idea is pretty simple,you agree on the small number of REST verbs. You then have interfaces that are specified by URL and a version number (perhaps part of URL). You then allow clients to specify their version number in a request.
This is discussed in a couple of InfoQ talks. Alex Antonov gave Case Study: RESTful Web Services at Orbitz. He shows how Protocol Buffers allow for efficient (he claims 7 times faster than SOAP) and flexible message passing using HTTP. Protocol Buffers is an open source HTTP messaging protocol developed by Google. The exchanged data uses protobuf.
Steve Vinoski gives a great talk on RPC and its fundamental flaws. He was an expert in CORBA in the 90's and he has recently moved to REST and Erlang. He is quite convinced that functional programming is the future and that imperative languages, such as Java and C# are based upon a the wrong model of distributed programming.
These talks dovetail nicely with Kirk Wylie's earlier InfoQ talk, Restful approaches to financial systems.
Saturday, January 23, 2010
Google Sites - easy project web sites
Friday, January 8, 2010
Grails: By the numbers
Thursday, October 1, 2009
Erlang, Mochiweb and Webmachine
Have a look. I was impressed by the clean design, but I was blown away by the debugger described in the last ten minutes. This is an open source project in Erlang, the high concurrency functional language created by Joe Armstrong at Ericsson. As noted in the talk, Webmachine is a high quality component to include in a web framework, like Mochiweb. Mochiweb itself is interesting: it is an Erlang framework for high concurrency web applications. When serving static content, it has been compared with yaws and nginx in a deathmatch on Joes Blog! Richard Jones is contemplating a Million User Comet App. Erlang is turning into a pretty cool language for web apps with high concurrency.
I wonder if there is any attempt to write an equivalent in Scala, a high concurrency functional language for the JVM? I have got to get up to speed with Scala and Lift. There is a lot going on here...
Saturday, September 26, 2009
Involve them in the same conspiracy
renegade spreadsheets and desktop databases that are wreaking havoc on organizations. Since then, many people have adopted the term because it highlights a painful, yet largely ignored, problem that plagues organizations today.
Spreadmarts contain vital pieces of corporate data that are needed to run the business. But since spreadmarts are created by individuals at different times using different data sources and rules for defining metrics, they create a fractured view of the enterprise. Without a single version of corporate data and centrally defined metrics, employees can’t share a common understanding the business. With spreadmarts, each worker marches to the “beat of their own drummer” instead of marching together toward a common goal. In short, spreadmarts undermine corporate productivity and sabotage business alignment.
Saturday, September 19, 2009
Comp Sci 61A - Online lectures
| Topic | studied in... |
| Application Program | CS 61A |
| High level language (Scheme) | CS 61B |
| Low Level Langauge (C) | CS 61C |
| Machine Langauge/architecture | ... |
| circuit elements | EE |
| transistors | applied physics |
| solid state physics | Physics |
| Quantum Mechanics | Physics |
Sunday, September 6, 2009
Slowly Changing DImensions, Type 6 = Type 1 + Type 2 + Type 3
Sunday, August 30, 2009
PosgreSQL: how to run on EC2 with EBS
Saturday, August 29, 2009
A virtual IT department: the database
Sunday, August 16, 2009
PostgreSQL: the EnterpriseDB webcasts
SQL Server and clustered indexes
When a database reads a range of values, a very common case, you may to read many values and IO usually becomes performance limiting. These values reside on your data storage, which is almost always a hard drive or a RAID array of hard drives. To make the IO faster, there are some basic strategies.
First you can make the data more compact. As an extreme example, consider the case of Decisionmark's Census Counts. This product provided a database with US Census Bureau Data distributed on a CD. Watcom SQL Anywhere, now Sybase SQL Anywhere, was used in part because we could compress each row. Compared with a hard drive, a CD has very slow data reads. So it was faster to read data from compressed rows and to unzip the data than it would have been to just read the same data uncompressed. Since SQL Anywhere's census data was read-only, we didn't need to worry about the write performance.
If you read about some modern database research, you will see that compressing data is one significant strategy in improving performance. For example, in MonetDB/X100 - A DBMS In The CPU Cache Zukowski and co-workers report
Figure 5 show the speedup of the decompressed queries to be close to the compression ratio, which in case of TPC-H allows for a bandwidth (and performance) increase of a factor 3.
So this is still an area of ongoing work at the frontier of research. The goal is maximizing the amount of data in each block of storage, so that IO is minimized and performance is maximized.
A second strategy is to use indexes. An index is a small bit of data that helps you quickly find the larger data recorded in your row. An index is build by looking at the values of some subset of your row, e.g., one or a few columns. For each value of the indexed value, you have a pointer to the row that holds the data. If you have a hash index, the pointer is directly to the row, and if you have a b-tree index, you may have to traverse a few nodes in the tree before you actually get a reference to the data row. If there is an index that is relevant for a query, it can speed that query significantly. It can do this by either reducing the IO to find the data (the database engine might otherwise have to read the entire table) or, in many cases, allow the database to avoid reading the table and simply use the index. Careful choices of indexes can vastly improve performance
A third strategy to improve read performance is physically order the data so that the data for your queries is adjacent on the hard drive. Unless you are using a solid state drive, you need to be moving the head and rotating the platter to read data. If the database can read adjacent blocks, it will read faster. In a typical query, the database engine will use the index to build a list of blocks that need to be read. If blocks are sequential, they can be read more quickly.
After laying this groundwork, I will now discuss what seems to be a fundamental problem with SQL Servers implementation of table ordering. In many databases, there is a command that allows the records in a table to be ordered by an index. To have a concrete example, consider the case of a department store chain. The chain has a computer system that records each sale in a purchase table. The chain has several stores, several departments, many sales representatives and many clients. To maximize the performance of our purchase table, you may want to order the records by (store, department, sales rep). For example, in PostgreSQL, you can create an index with create index index_purchase_store_dept on purchase (store_id, department_id, order_id). You can then order the table records with the command cluster index_purchase_store_dept on purchase. The database engine will then order the data in the purchase table using the index. This could significantly speed up reports of store or department. DB2 has a similar concept, where you can define an index to be cluster index for a table, you can then reorganize the table using the REORG utility. Oracle has a slightly different tactic: a cluster is defined in a schema. You can include up to 32 tables in the cluster and you can define an index to order the tables in the cluster. This means that not only are the rows in a given table close together, but rows from these tables will be close together. This takes the idea of clustering to a new level. Donald Burleson, author of Oracle Tuning, describes how these clusters are used. When records are added to any table in the cluster, they are placed into overflow blocks if there is no more room in the block specified by the index. When the overflow blocks reach as percent specified in PCTFREE, the records added to the tables get reorganized by the index.
SQL Server, as well as MySQL, makes clustering more convenient by defining an index to be clustered. You may declare one index per table to be the clustered index. To maximize the performance of our purchase table, you may want to order the records by either (store, department, sales rep) or perhaps by (customer). When records are inserted, they are insert in the order specified by the index. As carefully described in a blog by Sunil Agarwal, a Program Manager in the SQL Server Storage Engine Group at Microsoft, this will result in a severely fragmented table.
Instead, Microsoft urges the user to define the primary key to be an auto-generated integer and to cluster the table on the primary key's index. In other words, order the table chronologically. This seems to fundamentally contradict the concept of clustering. The records are 'clustered' in groups of one and they groups must be in chronological order. I checked some tables that followed this rule, and they all had 0% (or at least under 1%) fragmentation on the clustered index, even after a year of operation without maintenance.
Recently, I was asked to improve the performance of set of queries that were run against a SQL Server 2000. A review of the index statistics showed severe fragmentation, for the reasons outlined by Sunil Agarwal. To see if defragmenting would matter, I followed the advice in Microsoft SQL Server 2000 Index Defragmentation Best Practices. I defragmented the tables used in one particularly slow query. I was able to reduce the query time from over 4 minutes to just under 10 seconds. With a rewrite of the query, the query time dropped to under a second. However, after only two days of transaction processing, the clustered index had a fragmentation of over 40%. The query times were not back to the 4 minute level, but the formerly sub-second query was taking more than 10 seconds. In this case, the indexes are fragmenting faster than we could reasonably defragment them, since we cannot take this server offline daily to reindex the tables and using DBCC INDEXDEFRAG is simply too slow.
My conclusion is that in order to make clustered indexes useful, you need to be able to append a significant number of rows to a table and then order those records using the clustered index. Microsoft's solution of inserting each record at the location specified by the clustered index can rapidly cause severe fragmentation. The solutions of PostgreSQL, Oracle and DB2 avoid this issue, but at the cost of additional maintenance.