Improve developer habits by showing time cost of DB queries
danbirken.com
danbirken.com
Here's a screenshot expanded version of our staff bar on GitHub.com:
http://cl.ly/image/0O0N183x2F44
Most of those numbers are clickable. The graphs button on the left links to a flame graph (https://www.google.com/search?q=flame+graph) Ruby calls of the page. The microscope button is a sorted listing of CPU time and idle time by file that went into the page's render. The template number links to a timing breakdown of all the partials that went into the view. The SQL timing links to a breakdown of MySQL queries for that page, calling out N+1 queries, slow queries, or otherwise horrible database decisions. Depending on the page, we'll also have numbers for duration and queries spent in redis, elasticsearch, and gitrpc.
Our main github.com stuff is pretty tied into our stack, but one of our employees, Garrett Bjerkhoel, extracted a lot of this into peek, a very similar implementation of what we have on GitHub. We use peek in a ton of our smaller apps around the company. Here's the org: https://github.com/peek
It was a lot of fun to write and has been just as fun to use. We've found a number of simple changes that led to big performance gains on some of the pages.
I have deployed MiniProfiler on .NET, using only the default request introspection features. I am thinking about replacing it with Glimpse, but since neither one helps anyone but the current user (no long-term monitoring) it hasn't been used much.
http://www.techempower.com/benchmarks/#section=data-r8&hw=i7...
One framework for PHP developers that is worth looking into is Laravel. Very clean and reasonable framework. Have a look at it here: http://laravel.com/
For example, it has ActiveRecord by default, so you're focued around data stores... ideal for CRUD, but then its libraries to generate and validate forms are like something from 2008.
I'm a bit bemused as I must be missing something, given its popularity. Perhaps the apps I build are not a good fit for it - I'd be keen to have your input.
But not released yet, no vibrant community, it is like sensio's internal framework before symfony was released.
If you want to compare performance, do it yourself, don't believe someone else's benchmarks. Write a test case that is suitable for your reality, then go for a conclusion.
http://i.imgur.com/3d9sqFa.png
The sparkline in the bottom status bar lets you keep an eye on server request performance (single page app), and clicking it allows to see the details of the past 100 requests, including what DB calls were made and what parameters were used (great for finding slow queries and pulling them out to test and tune in isolation). The server tab gives overall php server and database statistics.
Our product has gotten a lot faster since integrating this, and I don't think that's a coincidence. It is extremely useful, and not just for performance optimization.
I have just made some crafty work in rails to make use of hstore datatypes in Rails. It stores an array of hashes, which I have not found a way to index the keys of yet.
Is this slow or fast for example? I'm doing a full-text search over all unnested (hstore) array values over a given column in a table wih 35k records.
development=# SELECT "leads".* FROM "leads" WHERE ( exists ( select * from (SELECT svals(unnest("address"))) x(item) where x.item LIKE '%mst%') );
Time: 57.257 msI'm used to MySQL, and this kind of query over unindexed records seems fast, but it also seems this might be slow for Postgres standards ?:/ Bear in mind.. no indices.
You may have to write a function that does what you want and Mark it as immutable.
They will also show you the sql (useful when it is generated by an orm) and breakdown each queries time cost.
* Showplan XML (Statistics Profile)
* SP:StmtCompleted
* SQL:StmtCompleted
(I think there's an RPC:StmtCompleted that's useful in some circumstances but I don't use it.)
Personally I pay more attention to the execution plans [1] than execution times, unless you have lots of data (indicative of what's on your production database) in your development database all your queries will complete quickly (table scans, nested loop joins and all).
You also see the N+1 problem very quickly when you're presented with a wall of trace results.
This isn't a silver bullet, but it's been a very long time since I've let any significantly suboptimal query get to production.
[1] Some difficulty arises with small development databases, because SQL Server will frequently scan a clustered index instead of a non-clustered index + clustered seek/key lookup because it's quicker to do the one thing. In this case you have to understand that the query is not bad and treating the clustered index scan as "bad" is not correct.
For Rails, there's https://github.com/josevalim/rails-footnotes.
Forgive/correct me if there are newer or better alternatives.
MiniProfiler- https://github.com/MiniProfiler/rack-mini-profiler- from the Railscast[0]- "MiniProfiler allows you to see the speed of a request conveniently on the page. It also shows the SQL queries performed and allows you to profile a specific block of code."
Bullet- https://github.com/flyerhzm/bullet- from the Railscast[1]- "Bullet will notify you of database queries that can potentially be improved through eager loading or counter cache column. A variety of notification alerts are supported."
When I was in that role, I combined education, public humiliation, cajoling and various administrative means to discourage bad database behaviors or optimize databases for necessary workloads. The median developer can barely spell SQL... Adult supervision helps.
Whatever I was making then, I probably recovered 3-5x my income by avoiding needless infrastructure and licensing investments.
Jokes aside, I still think profiling is a great idea here. Even if you're not responsible for writing the database portion, it's important to see how much time those calls are taking.
ruby: https://github.com/MiniProfiler/rack-mini-profiler
.net: https://github.com/MiniProfiler/dotnet
go: https://github.com/MiniProfiler/go (w/ support for app engine, revel, martini, and others)
If there is a python dev who wants to port MiniProfiler to python, I would love to help (I'm a MiniProfiler maintainer and did the go port). The UI is all done, you just spit out some JSON and include the js file. Kamens has a good port, but it's not based on this new UI library.
It also lets you dynamically enable/disable the introspection so you could run it in production.
<!--
head in <?php echo number_format($head_microttime, 4); ?> s
body in <?php echo number_format(microtime(true) - $starttime, 4); ?> s
<?php echo count($database->run_queries); ?> queries
<?php if (DEBUG) print_r($database->run_queries); ?>
-->Example output:
<!--
head in 0.3452 s
body in 0.7256 s
32 queries
Array(
[/Volumes/data/Sites/najnehnutelnosti/framework/initialize.php25] => SELECT name,value FROM settings
[/Volumes/data/Sites/najnehnutelnosti/framework/initialize.php45] => SELECT * FROM mod_captcha_control LIMIT 1
[/Volumes/data/Sites/najnehnutelnosti/framework/class.frontend.php123] => SELECT * FROM pages WHERE page_id = '1'
[/Volumes/data/Sites/najnehnutelnosti/framework/class.wb.php96] => SELECT publ_start,publ_end FROM sections WHERE page_id = '1'
[/Volumes/data/Sites/najnehnutelnosti/framework/frontend.functions.php28] => SELECT directory FROM addons WHERE type = 'module' AND function = 'snippet'
...etc
)
-->The array keys are the file from which the query originates with line number and the value is the query. I made it due duplicate queries. Query method in my class.database.php for the above output: public $run_queries = array();
function query($statement) {
$mysql = new mysql();
$mysql->query($statement);
$backtrace = debug_backtrace();
$this->run_queries[$backtrace[0]['file'].$backtrace[0]['line']] = $statement;
$this->set_error($mysql->error());
if($mysql->error()) {
return null;
} else {
return $mysql;
}
}SQL servers can be faster places to carry out certain types of operations on data, and it may be quicker to write the right kind of query for the server, than choose a very quick query and have to spend time on the front end processing that data.
The ultimate goal is time to eyeballs, not fastest query time. The best achieve that is to measure every stage not just queries, and spend time profiling and experimenting with various operations.
Example from google: http://blog.japanesetesting.com/wp-content/uploads/2009/11/d...
I suppose it writes to response headers that the chrome extension picks up?
Best part of the performance monitoring is that if the Request spans multiple Servers (load balancer/proxy, web-app, microservices, DB, etc), I can see it as a single transaction so that I can easily track down which Microservice that caused the performance slowness. For example, we have a web-app written in Python and a Microservice written in Java. A single request can end up at the Microservice level and our tool can see truly end-to-end => load balancer to web-app to microservice to database.
On top of that, we also have an app that performs synthetic monitoring where I can set to automate certain User workflow and set it to run every 5 minutes. Combining both performance monitoring and synthetic monitoring give us a leg up on automating performance monitoring!
Disclaimer: I work for AppNeta.
https://github.com/pylons/pyramid_debugtoolbar
The cool thing is that you can also click on EXPLAIN and get back information from the DB directly on what indexes it is using/maybe not using.
But most of us create small projects, pre-optimizing would be a hassle and useless for the client (pre-omitizing just costs more).
If you're a startup, you should use this, not for creating smb client software/webapps.
- add `define( 'SAVEQUERIES', true );` to your wp-config.php
- add `global $wp;var_dump( $wp->queries );` at the bottom of your scripthttps://github.com/cleanforestco/cfs-dev-tools/
From the Readme: This WordPress plugin allows you to easily place various development notes throughout your website. The development notes will appear on your page and the browser's console only when:
* You are working on your local development environment.
* You are logged into WordPress.
* ?devnote is appended to the URL.
One of the features is that it display in the page's footer the total number of SQL queries performed on the page and the total time required to generate the page. It also displays every SQL used to generate the page.
There are a few other features such as colour-coded CSS debugging, etc.
Contributors and feedback welcome :-)
Next, sort pages by query time and optimize them first.