What is the last event fired in Magento?

controller_front_send_response_after

What is the first event fired in Magento?

controller_front_init_before

Technically, it’s resource_get_tablename, but the first usable event is controller_front_init_before.

But this is also a bit of a trick question.  controller_front_init_before is ONLY triggered from the global area.  The first usable event in the frontend (or adminhtml) area is controller_action_predispatch.  core_locale_set_locale might also be a possibility because it is set when the area is loaded, but I would say that controller_action_predispatch is still the best, first usable event once the area is known.

4 charts that are guaranteed to make you a better performance detective

I was giving the Magento Performance and Optimization for System Administrator’s course today and I said something that is either borderline brilliant, stupid, or common knowledge.  What I said was something along the lines of “finding performance problems is about finding a) correlations, or b) deviations“.  In other words, a big part of determining a performance problem, especially when using instrumentation data as opposed to reviewing code, a prime goal is to find data that correlates or deviates.

To illustrate this I rendered 4 charts top illustrate what I meant.

2014-04-04_1125

 

What I mean by this is that when you are determining performance problems whose cause is not readily apparent you should be looking for data that correlates either inversely or proportionally (top row) or deviates (bottom row).

What do you think?  We must always grant that there will be cases where this is not true.  However, it seems that it many scenarios finding either a) correlating data, or b) deviating data gets you about 3/4 of the way to discovering the source of a performance issue.

On the state of software development communities and industry

[Post redacted due to concerns that any tenets deliberated or propositions discussed will be intentionally misrepresented or used as reductio ad ridiculum and may be used as fodder for personal attacks, loss of standing or accusations of misconduct]

I’m actually really excited about Hack and HHVM

When you get to be my age you start thinking about the future.  You start wondering if some of the choices you made when you were younger.  You wonder if those choices are going to come back and haunt you.  If you don’t have such thoughts you are either an idiot, or a young person without enough experience to make you think such things.

One of the things that I have been wondering about is whether my decision to focus on PHP several years ago was the right one.  Technology is always changing and eventually the guys writing Ruby, too, will start having children and then will start looking down upon people who use disposable diapers instead of more environmentally friendly cloth instead.  In other words, times change and one of the keys to navigating change is to know what to change, why to change and when, if ever, change is necessary.  Change for the sake of change is stupid.

There are several changes that are occurring in technology.  But one thing that has not changed has been the venom that PHP has been on the receiving end.  Much of the venom is, in fact, deserved, though the quantity by which the venom is spewed is not.  If you are the source of 75% of the traffic on the Internet then you might be doing something right.  But that 75% is today.  What about tomorrow?

And so my question has been “will there be enough innovation in PHP to keep it a force to be reckoned with several years down the road?”  I ask this because there are market and technology changes occurring that PHP is not well suited to navigate.

But before you think that I am totally down on PHP that is not quite true.  PHP was a revolutionary force when the web first came out.  It, and not any other programming language, democratized the web in a way that was not otherwise possible at the time.  But with the web won PHP kind of sat on its laurels for a bit.  Because of this several different languages have gained a foothold.  While PHP won the initial battle for the web (and did it convincingly) it did not protect its flank through continued innovation.  Innovation occurred to some extent, but PHP did not really mature.  In fact, I would argue that Ruby did what market forces are supposed to do to competitors ; forced them to step up them game.

And PHP did.  Within the span of just a few years framework after framework shot up.  The running joke was Q: “How many frameworks are there today?” A “That depends.  Is it Wednesday or Thursday?”  Ruby threatened and PHP responded.  Symfony, Zend, Laravel, Cake and a host others that I am not listing matured the PHP community very quickly.  What was once a hack language grew into a much more mature ecosystem.

But again, PHP seems to have stagnated a little.  There have been several people who have noted dis-function in PHP internals.  I’m not involved that close with that and so I have no definite statement I am willing to make.  However I have been concerned and what I am perceiving to be a slowdown of innovation since PHP 5.3 came out.

But the hack language may be on the verse of another jump forward via the Hack language and the HipHop VM.  While I, as a metalhead, object to the naming of the aforementioned VM with the release of version 3 we may be seeing something that could possible extend PHP’s life by 10-15 years and introduce another round of innovation for PHP.

With version 3 the excitement is almost palpable.  Davey Shafik and Padraic Brady have written blog posts recently that are the source of my optimism.  Resource utilization is a significant concern of mine at Magento (where I work now).  Magento does some really great things but does them at a fairly significant cost of CPU time.  If you’ve played with Customer Segments in EE you know what I’m talking about.  or, for that matter, rendering the layout.  When I was working at Zend I was constantly asked “what switch do I need to make PHP faster?” and an opcode cache can only do so much.  With Hack and HHVM that, quite literal, is a possibility.  In the spirit of full disclosure, I have not had a chance to play with it in depth and I hope to be able to soon, but the potential is there.

And that potential is something to be excited about.  Facebook has demonstrated significant resolve in building the HHVM.  It, like PHP to begin with, was built to solve a real problem; the problem of moving an old language into new times.

And maybe, just maybe, solving that problem will help keep PHP in the position it is in.  Maybe an old dog can be taught new tricks.

 

Now if only someone could provide my wishes of core low level event APIs and easy messaging integration.

assertTrue( ): Amazon: The Everything Company

If you’re thinking about putting your company’s Web presence on Amazon’s computers (using EC2), you might want to ask yourself a few questions. Does Amazon already compete with your business in any way? How long before Amazon does compete with you? Do you want to put your online business in the hands of a potential competitor? Do you want Amazon to know more about your business than it already does? No one’s suggesting Amazon is actually going to spy on your business’s bits and bytes (which are already encrypted anyway, right?), but they can learn a lot simply by knowing your capacity needs, your business’s Web traffic patterns, your scale-out and failover strategies. Just by metering your Web usage, they know too much.

via assertTrue( ): Amazon: The Everything Company.

Magento memory utilization for backend work

I was talking with a colleague about my previous blog post on memory utilization in Magento and he noted that I had not taken into account backend tasks.  Which he was right about.  So I decided to take a second look at the memory usage from the point of view of the admin UI.

But before we do that, let the caveats begin!  Firstly, this was with the sample Magento dataset.  Second, there were no additional modules (beyond Aoe_Scheduler and Alanstormdotcom_Systemsearch).  Third, just because these numbers show low usage does NOT mean you should drop memory_limit down to 32MB.

Read the previous post to see the methodology.

dataflow-export

 

Dataflow Export

reindex

 

Reindexing All Indexes

save-bundle-product

 

Saving a Bundled Product

save-simple

Saving a Simple Product

 

Using events in Magento 2

With the minimal research I have done on Magento 2 recently the only thing I am apprehensive about is the invocation chain.  Its purpose is to open the doors wide open to where you can hook your application in.  I suppose that’s not a bad goal, though I do think that there is wisdom in creative restraint.  Additionally, I don’t like code generation, which is what it uses.  I never have and probably never will.

But why am I saying that at the beginning of a blog post on using events in Magento 2?  That’s because the premise of the invocation chain is that events are going to be less important than they were before.  That’s not to say that they won’t be important, only that they will be less important.  In Magento 1 if you wanted to integrate with the system you needed events (or you could modify core files… which would give you a taste of the back of me hand).  In Magento 2 you might need events.

One of the things that has not changed between Magentos is is the notion of an area.  You still have adminhtml and frontend.  However, instead of having their own node in an XML document they have their own XML files.  Or, more correctly, their more XML file directories.  Event observers are declared in an events.xml file but where those observers are active will depend on the location of an events.xml file.  They will always be under <module>/etc.  If it is in that directory then the event will be watched globally.  If it is under etc/frontend, then it will be observed only when the frontend area is active and the same for adminhtml.  I really like this split.

In terms of declaring an observer a lot has changed, and it’s for the better.  One of the things that was problematic with Magento 1 is that observers needed to be defined under a unique XML node and if there was an accidental collision one of those observers the last merged node would be the one that would win out.  It didn’t happen often, but it was a potential side effect due to the nature of the system.  Now instead of silently overwriting the value you will get an error such as “Duplicate key-sequence ['controller_action_predispatch'] in unique identity-constraint ‘uniqueEventName’” if your observer has a duplicate name.

Configuring an observer is stupid easy.  No more memorization of “OK, I’m going to put this under /config/global/observers… no, wait.  /config/global/events/observers … no…”.  It is this:

<?xml version="1.0" encoding="UTF-8"?>
 <config>
   <event name="controller_action_predispatch">
   <observer
     name="eschrade_helloworld_echo"
     instance="Eschrade\HelloWorld\Model\Observer"
     method="echoHello" />
   </event>
 </config>

The code for our observer is very similar to how it looked in Magento 1.

1
2
3
4
5
6
7
8
9
namespace Eschrade\HelloWorld\Model;
 
class Observer
{
  public function echoHello(\Magento\Event\Observer $observer)
  {
    echo 'Hello World';
  }
}

This code echos “Hello World” when the “controller_action_predispatch” event is triggered.  Pretty simple.

But this is a poor example.  Why?  Because I’m echoing the content.  There is a dependency I need to properly handle output.  So, as with dependency injection I simply define what I need in the constructor (I have not blogged about this functionality in detail yet, but you don’t need to know the underlying implementation and you can trust that this works as displayed here).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace Eschrade\HelloWorld\Model;
 
class Observer
{
  protected $_response;
 
  public function __construct(
    \Magento\App\Response\Http $response
  ) {
    $this->_response = $response;
  }
 
  public function echoHello(\Magento\Event\Observer $observer)
  {
    $this->_response->appendBody('Hello World');
  }
}

There.  That is how you get things done.  And did you notice that you didn’t need to know anything about dependency injection?  It all kind of work itself out.  It’s even stupider easier to observe events in Magento 2.

But how about triggering them?  It’s a little harder, but not by much.  Did you see earlier where we needed to define a dependency for the response object if we wanted to use it later on?  We simply need to do the same thing for the class \Magento\Event\Manager.  There is no more Mage::app()->dispatchEvent(… and this is a good thing.  It makes for much better testing.  So if you want to trigger an event you simple define the event manager as a dependency.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace Eschrade\HelloWorld\Model;
 
class Observer
{
  protected $_response;
  protected $_eventManager;
 
  public function __construct(
    \Magento\App\Response\Http $response,
    \Magento\Event\Manager $manager
  ) {
    $this->_response = $response;
    $this->_eventManager = $manager;
  }
 
  public function echoHello(\Magento\Event\Observer $observer)
  {
    $this->_response->appendBody('Hello World');
    $this->_eventManager->dispatch('eschrade_echo_helloworld');
  }
 
  public function catchEvent(\Magento\Event\Observer $observer)
  {
    $this->_response->appendBody('Observed event');
  }
}

In our constructor we defined the event manager as a dependency and in the echoHello() method we call the dispatch() method on it.  But simply dispatching the event will not call the catchEvent() method.  In order to do that we need to modify the events.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<config>
 <event name="controller_action_predispatch">
   <observer name="eschrade_helloworld_echo"
     instance="Eschrade\HelloWorld\Model\Observer"
     method="echoHello" />
 </event>
 <event name="eschrade_echo_helloworld">
   <observer name="eschrade_helloworld_echo"
     instance="Eschrade\HelloWorld\Model\Observer"
     method="catchEvent"
     shared="false" />
 </event>
</config>

In this updated configuration file we added the second event which defined the observer configuration.  It’s pretty much exactly the same as the previous definition except that we are observing the event that our observer dispatches (though I would not recommend doing too many nested events).  But I added an additional attribute called “shared” which I set to “false”.  When the event manager dispatches an event it retrieves the observer object from the dependency injection container.  But whether it asks the DI container for a shared object (the default) or a new object depends on the value of the “shared” attribute.  If it is set to false it calls the create() method on the DI container.  For all other scenarios it calls get() which checks the shared instance property for an existing object of the type prior to returning it.

So there you have it.  Basic events in Magento 2.

Performance of Apache 2.4 with the event MPM compared to Nginx

I wrote a little while ago about how, for running PHP, Nginx was not faster than Apache.  At first I figured that it would be and then it turned out not to be, though only by a bit.

But since Apache also has an event-based MPM I wanted to see if the opposite results were true; that if Apache were using its event MPM it would be about the same as Nginx.  I had heard that Apache 2.2′s event MPM wasn’t great (it was experimental) but that 2.4 was better, possibly even faster, than Nginx.

So I had a few spare moments this Friday and figured I would try it out.   I basically ran ab at concurrency levels of 1, 10, 25, 50, 100 and 1000.  Like before the results surprised me.

event-mpm-nginx

 

The first run with Nginx was impressive.  It peaked at 14,000 requests per second.  Given my wimpy VM that  I ran it on, those numbers are pretty good.  What surprised me was that Apache was only half that.  I will say for the record that I do not know how to tune the event MPM.  But I don’t really have to tune Nginx to get 14k requests per second so I was expecting a little better from Apache.  So I pulled out all of the LoadModule statements I could but still have a functional implementation of Apache.  While the numbers were 25% better or so they were still well shy of what Nginx was capable of.  Then I added the prefork MPM to provide a baseline.  Again, I was surprised.  The event MPM was faster than the prefork MPM for static content, but not by much.

So it seems that if you are serving static content Nginx is still your best bet.  If you are serving static content from a CDN or have a load balancer in front of Apache which is running PHP then the prefork MPM is the way to go.  While the event MPM will help with concurrency it will not help you speed up PHP and so is not really needed.

(Basic) Configuring the Magento 2 Dependency Injection Container

My previous blog post on the DIC (Dependency Injection Container) in Magento 2 covered just some basics of using the Magento 2 DIC.  The purpose of that post was to, perhaps, make you less apprehensive about using DI combined with the DIC in Magento 2.  However, in this post I want to go a little deeper into the DIC, implemented via the Magento\ObjectManager\ObjectManager class, and talk about how to configure it.

Configuration for the DIC is done in each module’s etc/di.xml file or etc/<area>/di.xml.  Because you can split DIC configuration based on the area this tells you that the /config/<area> naming stuff is over; which I applaud.  The configuration file has the standard /config base node, but then can have child nodes that are named “type”, “preference” or “virtualType”.  We will focus on “type” and “preference” here.

Type

The first configuration type we will look at is the “type” element.  This is used to give the DIC instructions on configuring the object that has been requested.  There are several instructions that can be given be we are going to focus, for the time being, on the “param” setting.  We will start by creating a new module called Eschrade\HelloWorld.

In that module we are going to create a class called Eschrade\HelloWorld\Model\Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace Eschrade\HelloWorld\Model;
 
class Test
{
  protected $message;
 
  public function __construct($message)
  {
    $this->message = $message;
  }
 
  public function getMessage()
  {
    return $this->message;
  }
}

In order for us to get an instance of that class we need to call the DIC’s create() method.  In the previous blog post we called get().  We will get to that.

So how do we fulfill the requirement for the $message constructor argument?  The second parameter in the DIC’s create() method is that of arguments.  In other words, via the create() method you can inject your own data into the class.

1
2
3
4
5
6
7
8
9
10
11
12
use Magento\App\ObjectManagerFactory;
require_once 'app/bootstrap.php';
 
$locatorFactory = new ObjectManagerFactory();
$om = $locatorFactory->create(__DIR__, $_SERVER);
$test = $om->create(
  'Eschrade\HelloWorld\Model\Test',
  array(
    'message' => 'Hello World'
  )
);
echo $test->getMessage();

When we run this code we get

Hello World

Exactly what we placed in the argument.

But what if there are options you want to pass into the constructor that the classes with the dependency wouldn’t know about.  Some examples could be configuration strings, cache prefixes, template values and so on.  Requiring a class with a dependency to know how to fulfill one of the dependencies of its dependency would be a pain to manage.  To manage such things we now need to look at an example di.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <type name="Eschrade\HelloWorld\Model\Test">
    <param name="message">
      <value>Hello World</value>
    </param>
  </type>
</config>

One of the things you might have gotten used to in Magento 1 was arbitrarily throwing XML in wherever you want it.  That is not the case with Magento 2, particularly when it comes to the DIC.  In this case <type> is a node that has a certain definition (it can be found in lib/Magento/ObjectManager/etc/config.xsd).  This node has certain attributes and child nodes that it can have.  One attribute is “name” which tells the DIC the class name that this configuration element is referring to.  This is the fully qualified class name.

As a child node, one of the options is <param> (another is <instance> which we will not look at here).  It also requires a parameter called name which must match the name of the constructor argument, in this case “message”.  <value> is also a required node name and it contains the value of the string that will be passed in to the constructor.

We will now change our code a little to call get() instead of create() on the DIC.

1
2
3
4
5
$locatorFactory = new ObjectManagerFactory();
$om = $locatorFactory->create(__DIR__, $_SERVER);
 
$test = $om->get('Eschrade\HelloWorld\Model\Test');
echo $test->getMessage();

When we run this code we get

Hello World

Congratulations, you have now created a DIC configuration file.

Preference

A big part of using a DIC is the dependence on an interface to define the requirements of a given class.  This allows you to work on various implementation components in parallel while defining what it is this class will require.  Then, as part of unit testing, the interface can be mocked and provide sample data without depending on a concrete implementation of the interface.

So let’s change our Test model class to require an interface for its constructor.  We will call it Message and it will look like this.

1
2
3
4
5
6
namespace Eschrade\HelloWorld\Model;
 
interface Message
{
  public function getMessage();
}

Our Test model will now look like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace Eschrade\HelloWorld\Model;
 
class Test
{
  protected $message;
 
  public function __construct(Message $message)
  {
    $this->message = $message;
  }
 
  public function getMessage()
  {
    return $this->message->getMessage();
  }
}

If we were to run this code right now we would get an error stating that the DIC could not instantiate an instance of Message because it is an interface.  So we need to do two things.  We need to define a concrete instance of that class and then tell the DIC to use it instead of the interface.

1
2
3
4
5
6
7
8
9
namespace Eschrade\HelloWorld\Model;
 
class HelloWorld implements Message
{
  public function getMessage()
  {
    return 'Hello World';
  }
}

And now our di.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <preference
    for="Eschrade\HelloWorld\Model\Message"
    type="Eschrade\HelloWorld\Model\HelloWorld" 
  />
</config>

When we run the code

1
2
$test = $om->get('Eschrade\HelloWorld\Model\Test');
echo $test->getMessage();

We get

Hello World

Instance Parameters

As nice as that was it is not really feasible to have such global definitions all of the time.  And so this time we will use the <type> element to declare HelloWorld as being the proper implementation of Message.  Because all of the code has been written all we need to do is change di.xml.

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <type name="Eschrade\HelloWorld\Model\Test">
    <param name="message">
     <instance type="Eschrade\HelloWorld\Model\HelloWorld" />
    </param>
  </type>
</config>

When we run our test code we get the following output.

Hello World
Web Analytics