Whisky Advent: part 3

December 12th: Auchentoshan American Oak

day12-glass.jpg day12-label.jpg

Tonight's dram is an Auchentoshan American Oak. It's from a bottle that I received as a gift for speaking at Glasgow PHP. Thanks! This Auchentoshan does not have an age statement, giving the bottlers a bit more freedom in which ages of barrels they use to blend with. It is possible that whiskies as young as three years are part of this "blend". This specific whisky is aged in first-fill Bourbon casks. Unlike many other whiskies on this calendar, it is both chill filtered and coloured.

Tasting notes: Over ripe fruits, oak, and a sour grapefruit finish. It's a little bland, and it has a short finish. It's still quite enjoyable.

Morag says: Slightly sharp nose, a little bit like vanilla. Not the smoothest with a hint of roughness. Short finish. Tastes like cardboard (or woody). Does not compare well to the Three Wood.

December 13th: Cadenhead's Glen Moray 21 year old

day13-glass.jpg day13-label.jpg

Another dram from Cadenhead's. It is a 21 year old whisky, distilled in 1992. It is part of their Wine Cask range and as usual, it is non-chill filtered and no colouring has been added. The 1992 CA is bottled at 55.4% ABV cask strength. A little curious is that the distillery on the label is Glen Moray-Glenlivet — the "Glenlivet" addition is not often seen anymore. There were only 216, and I'm afraid they are all sold out.

Tasting notes: It does need a drop of water to bring out some flavours—at 55.4% it is just a little bit too strong. Hints of sweeter wine, and cake. Perhaps a hint of aniseed and a finish of medicinal herbs. I'm not quite sure what to make of it really.

December 14th: Single Cask Aberlour 22 years old

day14-glass.jpg day14-label.jpg

I recently found the Whiskybase online, and noticed its extensive list of available whiskies. However, the whisky I had tonight was not known to them yet. I have since then added it.

The whisky is a 22 year old, single cask, cask strength whisky bottled by Speciality Drinks . This casks rendered 250 bottles and at 54.1% ABV it is a bit on the stronger side, and needs a little bit of water. I bought it at the Whisky Exchange as the bottle of the month1 for July. Interestingly the label on my bottle is different than what they have on their site.

Tasting notes: It is a very clear whisky. I taste hints of apple and cream. And with more than a hint of toffee. It lingers quite long with a hint of more toffee.

December 15th: Mortlach Càrn Mòr Strictly Limited

day15-glass.jpg day15-label.jpg

Tonight's dram is a whisky from the Mortlach distillery. Another whisky that the Whiskybase did not have! Or rather, I thought so. The search engine insisted that I spelled it "Mortlach Càrn Mòr" and wouldn't find it if I used "Carn Mor" :-/

This whisky is not from a single cask, but rather from two casks yielding 652 bottles. The whisky is non-chill filtered and has no colouring added. It is bottled at 46% ABV by Morrison and MacKay for their Strictly Limited range. The "two" whiskies are at least 16 years old and aged in Hogshead casks.

Tasting notes: Smooth and creamy honey on the tongue. Light summer fruits and caramel after taste. Could do with a few drops of water to make the flavours come out more.

December 16th: Millstone 1999 from Milroy's

day16-glass.jpg day16-label.jpg

The first non Scottish whisky in this calendar. Tonight we have a Dutch whisky, distilled in 1999 by Zuidam Distillery, and bottled by Milroy's of Soho in 2013. This Millstone 1999 is one of 271 bottles of a 14 year old single cask whisky matured in Sherry Casks. It is 46% ABV and again, non-chill filtered and it does not have colouring added. The whisky itself is quite dark of colour, rather like a sherry.

Tasting notes: Raisins, cinnamon, and a sweet sherry. The medium to longer finish is a bit oily and has a hint of oak and cherries.

December 17th: Yamazaki 18

day17-glass.jpg day17-label.jpg

This Yamazaki 18 from Suntory distillery is another non-Scottish whisky. As the name might hint at, this is Japanese. Some people might frown upon that, but "annoyingly", the Japanese actually make very good whiskies. This one, the Yamazaki is one of my favourites, but it does not come cheap. Luckily, it was given to me as a gift for my work on Xdebug. Since this Yamazaki 18, I've had another whisky, the Hakushu Distiller's Reserve that I actually like better. But that's empty.

Tasting notes: Very dark of colour. A little oily on the palette. Bubblegum, apricot and sweet fruits, a few herbs and spices. Fruits and woody flavours in the aftertaste that lingers quite a bit.

December 18th: Imperial 1994

day18-glass.jpg day18-label.jpg

This Imperial 1994 is bottled by Gordon & MacPhail as part of their Distillery Labels range. It is a first fill sherry butt and refill American hogshead. As the name suggests, it was distilled in 1994. The Imperial distillery is now closed though. This whisky was bottled in 2012 making it 18 years old. It is 43% ABV.

Tasting notes: Smells sweet, fruity and nutty. Smooth on the palette and vanilla, pepper and some tropical fruits in the aftertaste.

Shortlink

This article has a short URL available: http://drck.me/whiskyad3-b77

Comments

No comments yet

Whisky Advent: part 2

December 5th: Blue Hanger, 8th Release

day5-glass.jpg day5-label.jpg

This Blue Hanger is the only blend on the calendar, but this is an unusual blend so I am making an exception. This 8th release is a 21 year old blend, bottled by Berry Bros. & Rudd. It is named after William Hanger, the 3rd Lord Coleraine, a loyal customer of Berry Bros. & Rudd during the late 18th century. He was renowned for the striking blue clothes he wore and gained the soubriquet, "Blue Hanger".

It is bottled at 45.6% ABV, with natural colouring and it is not chill filtered. It is exclusive to The Whisky Shop.

Tasting notes: Orange peel, vanilla, caramel. With a little bit of salt and smoke.

December 6th: Springbank 12 Green

day6-glass.jpg day6-label.jpg

As this month's whisky of the month, I went to my favourite whisky shop in London, Cadenhead's. They are best known for their single cask whiskies, and indeed many of the whiskies on this advent calendar come from them.

This Springbank 12 Green whisky is not a single cask whisky. But it is a very new whisky. So new, that I couldn't find it through Google yet. The label on the bottle says it's one out of 9000 bottles. It is called "Green" because it is distilled from organic barley.

It is matured entirely in bourbon casks and bottled at 46% ABV. The result is creamy and sweet with classic Springbank peatiness giving depth and a hint of coastal air.

Tasting notes: Very pale. Sweet fruits and a little bit peaty. The whisky lingers quite long with peat and a hint of sherry.

December 7th: Single Cask Ardmore 16

day7-glass.jpg day7-label.jpg

Tonight's dram is 16 years old, distilled in 1996 by Ardmore and bottled in

2012. It is one of 315 bottles from a refill Hogshead, selected by Douglas Laing. It forms part of Douglas Laing's Old Malt Cask range, and is now sold out.

Tasting notes: As an Ardmore it is quite peaty, with barley and all spice flavours. Spices, smoke and peppers are its overtones. There are hints of wood in the aftertaste.

December 8th: anCnoc 22

day8-glass.jpg day8-label.jpg

A typical winter warmer from anCnoc. It is 22 years old, and as usual in a natural colour and non-chill filtered. It is a standard whisky, made from many different casks - but aged in both ex-bourbon casks and ex-sherry butts.

Tasting notes: Honey, sweet and a few hints of all spice. A bit like Christmas cake. There is also a hint of smoke, and the whisky is general full of flavours. The finish is spicy.

December 9th: Glenburgie 1994

day9-glass.jpg day9-label.jpg

This 17 year old whisky is distilled by Glenburgie, and bottled by Gordon & MacPhail in 2012. It is specifically bottled for La Maison du Whisky in Paris, not far from Métro station Madeleine. It is in Paris that I bought this whisky when I was there for Forum PHP last year. La Maison du Whisky is in my opinion the best whisky shop outside of Scotland, and Cadenhead's in London.

As is common to many of my whiskies, this is again a non-chill filtered natural colour single cask whisky—cask 10055 in case you care. It is 45% ABV and matured in 1st fill sherry butts.

Tasting notes: The colour is slight red, and it is slightly oily on the tongue. Hints of caramel and honey, but more stronger spices such as cardamom and cloves. The after taste is a little bit zesty, and has hints of oak.

December 10th: Tomintoul 16

day10-bottle.jpg

I spoke at Glasgow PHP this evening, which meant that I couldn't do my regular bottle and a glass approach. I had to do with a miniature of a Tomintoul 16 that I had brought along. The organisers were so kind to gift me a bottle of Auchentoshan American Oak though, but I am saving that for an upcoming night.

Tasting notes: Overall quite bland, and I didn't pick out too many flavours. It's a bit fruity sweet, but the flavour doesn't linger and in a few seconds I had forgotten about it at all.

December 11th: Mannochmore 12

day11-glass.jpg day11-label.jpg

This latest whisky comes from the Mannochmore distillery, which produces for twelve months and then has a break of twelve months alternating with the nearby Glenlossie distillery, with which it shares the employees. A rather unusual arrangement if you ask me.

In one of the years, they did manage to distill the spirits that now end up as the Mannochmore 12, which I am enjoying tonight. It is part of Diageo's Flora and Fauna range.

Tasting notes: Honey and a hint of pepper? There is quite a lot of flavours coming into play after a while. And even a hint of ginger in the long lingering finish.

Shortlink

This article has a short URL available: http://drck.me/whiskyad2-b6x

Comments

No comments yet

Parallelizing document retrieval

This is an article I wrote a while ago, but apparently hadn't posted.

MongoDB 2.6 has a new feature that allows you to read all the documents from one collection with multiple cursors in parallel. This is done through a database command called parallelCollectionScan. The idea behind it is that it is faster then reading all the documents in a collection sequentially.

Just like the Aggregation Cursor, calling this command returns cursor information. However, it returns an array of these structures. Let run this example to see what it returns:

<?php
$m = new MongoClient;
$d = $m->demo;

$r = $d->command( [
    'parallelCollectionScan' => 'cities',
    'numCursors' => 3
] );

var_dump( $r );
?>

And this outputs (after some formatting):

array(2) {
  ["cursors"]=>
  array(3) {
    [0]=>
    array(2) {
      ["cursor"]=>
      array(3) {
        ["firstBatch"]=> array(0) { }
        ["ns"]=> string(14) "demo.cities"
        ["id"]=>
        object(MongoInt64)#5 (1) {
          ["value"]=> string(12) "339843550291"
        }
      }
      ["ok"]=> bool(true)
    }
    [1]=>
    array(2) {
      ["cursor"]=>
      array(3) {
        ["firstBatch"]=> array(0) { }
        ["ns"]=> string(14) "demo.cities"
        ["id"]=>
        object(MongoInt64)#6 (1) {
          ["value"]=> string(12) "340949759620"
        }
      }
      ["ok"]=> bool(true)
    }
    [2]=>
    array(2) {
      ...
    }
  }
  ["ok"]=> float(1)
}

With the MongoCommandCursor::createFromDocument from an earlier article you can create a MongoCommandCursor for each of the array elements:

<?php
$m = new MongoClient;
$d = $m->demo;

$r = $d->command( [
        'parallelCollectionScan' => 'cities',
        'numCursors' => 3
], null, $hash );

$cursors = [];
foreach( $r['cursors'] as $cursorInfo )
{
        $cursors[] = MongoCommandCursor::createFromDocument( $m, $hash, $cursorInfo );
}
?>

Instead of creating an array of cursors yourself, the driver implements the MongoCollection::parallelCollectionScan method. Making the above a little bit easier:

<?php
$m = new MongoClient;
$c = $m->demo->cities;

$cursors = $c->parallelCollectionScan( 3 );
?>

The idea is that with multiple cursors you can iterate over each of the segments in parallel, for example indifferent threads. Of course, PHP does not have threads so that you can't really run things in parallel. However, PHP does have a MultipleIterator class that allows you to iterate over multiple cursors at the same time:

<?php
$m = new MongoClient;
$c = $m->demo->cities;

$cursors = $c->parallelCollectionScan( 3 );


$multiple_it = new MultipleIterator( MultipleIterator::MIT_NEED_ANY );
foreach ( $cursors as $cursor )
{
        $multiple_it->attachIterator( $cursor );
}


foreach ( $multiple_it as $items )
{
        foreach ( $items as $item )
        {
                if ( $item !== NULL )
                {
                        echo $item['name'], "\n";
                }
        }
}
?>

There are three sections here. First we create the cursors with MongoCollection::parallelCollectionScan, then we collect the created cursors into a MultipleIterator and lastly we iterate over the $multiple_it iterator to get our results. Each iteration gives us an array of elements back. One element for each of the containing cursors (3 in our example). We need a second loop (foreach) to pick out the real document.

Not every contained cursor will provide the same amount of items, it is up to the MongoDB server to divide this. When a contained iterator is exhausted, the MultipleIterator sets the value to NULL. It is probably better to then remove that specific contained iterator from the MultipleIterator, but that is left as an excercise for the reader.

When running some benchmarks, I didn't actually see any performance benefit with multiple cursors over just one cursor, but that is likely because the cursors are still iterated over sequentially, and not in parallel. Perhaps using the pthreads PECL extension allows for a better benchmark, but right now, the PHP driver for MongoDB doesn't support threaded execution yet.

Shortlink

This article has a short URL available: http://drck.me/mongopcs-b6u

Comments

No comments yet

Whisky Advent: part 1

December 1st: Glenrothes 9, by Douglas (Sherry Butt)

day1-glass.jpg day1-label.jpg

The first whisky on the calendar is a 9 year old Glenrothes, bottled by Douglas. It is one out of 210 bottles of a single cask (#9928) distilled in 2004 and bottled in 2013, aged in a Sherry Butt.

Tasting notes: Oily on the tongue. Sherry flavours with a hint of fruits. Smokey after taste.

About Glenrothes: "Established by the burn of Rothes in Speyside in 1879, The Glenrothes distillery has been producing its characteristic Speyside single Malt for over 130 years. The maturity of The Glenrothes is determined not by age, but by Vintage, resulting in some memorable moments, captured forever in specific expressions of this remarkable spirit."

December 2nd: GlenGrant 170th anniversary

day2-glass.jpg day2-label.jpg

Tonight's dram is a GlenGrant 170th anniversary, bottled to commemorate the 170th anniversary of the Glen Grant distillery. Now owned by the Italian Gruppo Campari, the distillery was founded in 1840. It is a non-chill filtered whisky at 46% ABV.

Tasting notes: Sweet, raisins and rich fruits. Long finish with hints of peat smoke. Actually, a very long sherry flavoured finish.

December 3rd: Benromach 2001 Cask Strength

day3-glass.jpg day3-label.jpg

Tonight we have a dram from Benromach, a distillery that I actually visited as part of our big whisky trip last year. It is a 2001 cask strength whisky is matured in first fill Bourbon barrels, and no longer available. At 59.9% ABV it is stronger and benefits from a drop of water.

Tasting notes: Honey, sweet, and vanilla. I also taste some nuts, and a little bit of peat. Quite a nice dram, but it does definitely need a drop or two of water.

December 4th: Arran Single Cask Sherry

day4-glass.jpg day4-label.jpg

A single cask whisky from Arran distillery aged in Sherry Casks. It is 16 years old and one of only 269 bottles. It is going to be difficult to find another bottle. Amazon has 8 left, and this whisky is well worth its price. The whisky is at 55.3% ABV and of course non-chill filtered. It needs a drop of water for its flavours to fully develop.

Tasting notes: It's very much like sweet sherry, with hints of ginger and other spices.


This concludes the first four whiskies on the calendar. I am looking forward to the following 20!

Shortlink

This article has a short URL available: http://drck.me/whiskyad1-b6n

Comments

No comments yet

Code Coverage: The Present

Since ages Xdebug has provided code coverage support for PHPUnit, a way to show which lines are covered by your test cases. But I never really wrote about how it works. A recently filed bug prompted me to write this post, as well as a follow up post on Code Coverage's future.

In its earliest incarnation, Code Coverage overloaded only the EXT_STMT opcode. In a special mode of the Zend Engine, this extra opcode is generated between every statement — roughly whenever you use a semi-colon. Whenever that opcode is hit, I recorded on which line that was. Each line was then returned as part of a multi-dimensional array when you ran xdebug_get_code_coverage(). The top-level keys are the filename, the second level keys the line number, and its value a 1 if that line was hit. If a line was not hit, there would be no corresponding line number key in the array.

This approach didn't work out too well, as PHP doesn't always generate an EXT_STMT opcode when you want it too. Not only does this causes issues with breakpoints when single-stepping, but it also means that many lines in the code could never be hit. Take for example the following code:

1: <?php
2: $c = array(
3:      'name' => 'derickr',
4:      'age' => 'yeah right',
5: );
6: ?>

This array definition produces the following opcodes, PHP's internal representation of your code (simplified from vld output):

line     #* op                 return  operands
-------------------------------------------------
   3     0  EXT_STMT
                 1  INIT_ARRAY         ~0      'derickr', 'name'
   4     2  ADD_ARRAY_ELEMENT  ~0      'yeah+right', 'age'
   5     3  ASSIGN                     !0, ~0
   7     4  EXT_STMT
                 5  RETURN                     1

There is only an EXT_STMT generate on line 3 (the first array element) and on line 7 (which doesn't actually even exist!). If I would run this script with code coverage enabled, it would only show lines 3 and 7, clearly not adequate. This is why Xdebug's code coverage overloads a lot more opcodes: ZEND_JMP, ZEND_JMPZ, ZEND_JMPZ_EX, ZEND_JMPNZ, ZEND_IS_IDENTICAL, ZEND_IS_NOT_IDENTICAL, ZEND_IS_EQUAL, ZEND_IS_NOT_EQUAL, ZEND_IS_SMALLER, ZEND_IS_SMALLER_OR_EQUAL, ZEND_BOOL_NOT, ZEND_ADD, ZEND_SUB, ZEND_MUL, ZEND_DIV, ZEND_ADD_ARRAY_ELEMENT, ZEND_RETURN, ZEND_RETURN_BY_REF, ZEND_EXT_STMT, ZEND_RAISE_ABSTRACT_ERROR, ZEND_SEND_VAR, ZEND_SEND_VAR_NO_REF, ZEND_SEND_VAL, ZEND_NEW, ZEND_EXT_FCALL_BEGIN, ZEND_CATCH, ZEND_BOOL, ZEND_ADD_CHAR, ZEND_ADD_STRING, ZEND_INIT_ARRAY, ZEND_FETCH_DIM_R, ZEND_FETCH_OBJ_R, ZEND_FETCH_OBJ_W, ZEND_FETCH_OBJ_FUNC_ARG, ZEND_FETCH_DIM_FUNC_ARG, ZEND_FETCH_DIM_UNSET, ZEND_FETCH_OBJ_UNSET, ZEND_FETCH_CLASS, ZEND_FETCH_CONSTANT, ZEND_CONCAT, ZEND_ISSET_ISEMPTY_DIM_OBJ, ZEND_PRE_INC_OBJ, ZEND_SWITCH_FREE, ZEND_QM_ASSIGN, ZEND_DECLARE_LAMBDA_FUNCTION, ZEND_ADD_TRAIT, ZEND_BIND_TRAITS. And sometimes I have to add new ones for newer PHP versions.

Tip: Overloading opcodes makes PHP run slower and Xdebug will only do this when you have xdebug.coverage_enable set to on. This is the default value though, because of backwards compatibility reasons. You can speed up Xdebug a fair amount by turning this option off in your php.ini file.

Which lines have code on them?

Just enabling code coverage with the xdebug_start_code_coverage() function will give you every single line that has been hit while running your script. But it does not say anything about which lines you have not hit. Xdebug can also calculate this. In order to do so, the option XDEBUG_CC_UNUSED needs to be passed to xdebug_start_code_coverage(). Turning this specific option on makes Xdebug scan every execution unit (opcode) in your application. This adds a lot of overhead. Of course, Xdebug does try to analyse each function (or method) only once. A bug in this detection actually made it not scan as often as it should, but that will soon be fixed through PR #134.

Which lines can be executed?

Besides code coverage and finding out which lines can be covered, Xdebug can also find which parts of your code can never be reached: dead code.

I implemented the algorithms to find dead code in another one of my side projects first: vld. It is a tool that shows PHP's internal compilation units (opcodes), just like in the array example above. Because it is a much smaller and simpler tool, testing new algorithms out in it makes things a lot easier than trying to get it into Xdebug immediately.

Anyway, the dead code analysis can be activated by passing in the XDEBUG_CC_DEAD_CODE option. It does not make a lot of sense to do this without XDEBUG_CC_UNUSED and you can combine them with the | operator as they are parts of a bitfield:

xdebug_start_code_coverage( XDEBUG_CC_DEAD_CODE | XDEBUG_CC_UNUSED );

With dead code analysis enabled, Xdebug will scan each function and method's oparray as usual, but it will also follow all branch points (such as the ones created by if, while, for, etc.), to see which branches can not be reached theoretically. This finds for example return; before some other code, or a throw with code following. After following all the branch and exit points, Xdebug then finds which opcodes are not part of any branch. It eliminates them from the lines that can be executed, as found by the checks run for XDEBUG_CC_UNUSED.

In the resulting array structure that xdebug_get_code_coverage() returns, there are now three possible values for each line: 1, to signal that code has been executed, -1 if there was no code executed on that line, and -2 if there was no executable code at all on that specific line.

An example script (article-test.php):

<?php
function test()
{
        if ( $a == 42 )
        {
                echo "The argument is 42\n";
        }
        else
        {
                throw new Exception( "Not 42!" );
                echo "nope\n";
        }
}

try
{
        test( 42 );
}
catch ( Exception $e )
{
        echo "Do nothing!\n";
}
?>

Executed through a runner (article-simple.php):

<?php
xdebug_start_code_coverage( XDEBUG_CC_DEAD_CODE | XDEBUG_CC_UNUSED );

include 'article-test.php';

var_dump( xdebug_get_code_coverage() );
?>

Produces (after some formatting):

Do nothing!
array(2) {
  '/home/httpd/html/test/xdebug/code-coverage/article-test.php' =>
  array(12) {
        [2] => int(1)
        [4] => int(1)
        [5] => int(1)
        [6] => int(-1)
        [7] => int(-1)
        [10] => int(1)
        [11] => int(-2)
        [13] => int(-1)
        [17] => int(1)
        [19] => int(1)
        [21] => int(1)
        [24] => int(1)
  }
  '/home/httpd/html/test/xdebug/code-coverage/article-simple.php' =>
  array(2) {
        [4] => int(1)
        [6] => int(1)
  }
}

If we were to use PHP CodeCoverage instead, the runner script (article.php) looks like:

<?php
require 'vendor/autoload.php';

$coverage = new PHP_CodeCoverage;

$coverage->start( 'article' );

include 'article-test.php';

$coverage->stop();

$writer = new PHP_CodeCoverage_Report_HTML;
$writer->process($coverage, '/tmp/code-coverage-article');
?>

Which outputs:

code-coverage-current.png

Lines 6 and 7 have not been executed, because we didn't pass in the variable $a. Line 13 has not been executed because the code never reached the end of the function as we jumped out with the throw in line 10. The output also shows that the code on lines 11 and 12 can not be reached (because of the throw preceding it).

This concludes the current code coverage features in Xdebug, in the second part I will cover an upcoming feature.

Shortlink

This article has a short URL available: http://drck.me/codecoverage-b6k

Comments

No comments yet

  • 1

    The "bottle of the month" is a longer running project. I will blog about that at some point later.

  • 2

    The "bottle of the month" is a longer running project. I will blog about that at some point later.

Life Line