Sunday, 3 June 2018

Preface to idbg

Fig 1. A tweet from earlier this month
We already have several options for debugging code within the PHP ecosystem. XDebug is extremely mature software, and phpdbg has been slowly gaining traction also, if for no other reason than it's very fast to collect code coverage compared to XDebug.

Although phpdbg and XDebug are different from one another, they have some things in common: They are both complicated (to varying degrees), and they are both written in a language that 97% of the people reading this text do not understand (number pulled from air, based on nothing at all).

Why do we need a debugger at all?

Slightly tangential perhaps ... Debugging is a necessary part of writing code; If you disagree with this statement, then I don't know what you are talking about.

If debugging to you means sprinkling code with debugging statements like var_dump, or print_r, then I implore you to learn how to use a debugger; You are wasting a lot of time. I don't say this from a position of arrogance because I happen to be one of the authors of phpdbg, but from a position of experience; I remember trying to write code before I had a good handle on using a debugger. 

Sprinkling code with debugging statements is like crouching on a stool in the corner of a cockroach infested room and hoping that blowing upon the blanketed floor will destroy and eliminate the little beasts creating the blanket.

Using a debugger is like having an army of nano bots at your disposal, each one trained exquisitely in a top nano-bot-training-camp, they live to kill cockroaches, some of them also have mean looking tattoos, chew tobacco, and spit on the ground at the start of every sentence ...

I think we understand each other ...

Why do we need a debugger written in PHP ?

Here are some statistics (from github api):
  • XDebug has had 50 contributors in the 7 years it has been on github
  • phpdbg has had a handful of contributors (20-30) in the 4 and a half years it has been on github
  • PHPUnit has had 342 contributors in the 8 and a half years it has been on github
  • phpstan has had 70 contributors in the 2 and a half years it has been on github
XDebug predates it's github repository (by a very wide margin), still it doesn't matter for the point I'm trying to make here: In the PHP ecosystem, we have very many very talented programmers, with a whole host of knowledge about how the PHP engine works - they may have been using it for their entire professional career - they are able to write and contribute to arguably comparatively complicated software like PHPUnit or phpstan. Alas we have vanishingly few programmers in the ecosystem that are able to improve, fix, or develop in any way software like phpdbg or XDebug, and I think it's mostly because of the language they are written in.

You might also just like to scan the number of contributors to projects like Laravel and Symfony ... although I think these numbers less relevant, they are surprisingly high.

It's not all about the language, the domain specific knowledge required to implement a debugging engine might not be so disseminated. But maybe it doesn't need to be ...

You may not find these arguments convincing, you may not be convinced that we need another debugger written in any language, after all XDebug is extremely mature, and using phpdbg makes you at least 20% cooler (in the same way as go faster stripes make any vehicle 20% faster). That's a perfectly rationale position to take, and I can't think of another way to argue my case, you can probably stop reading ;)

Domain Specifics

I don't know how obvious it is that it's not reasonable to talk about implementing a debugger entirely in PHP; The kind of control you need over the engine just isn't reasonably attained in userland by default.

The debugger itself, the thing that interacts with a person or an ide can be written in PHP alone, and is much easier to write in PHP. But the core of the "debugging engine" (terminology borrowed from dbgp specification) should be written in C.

krakjoe/inspector is a disasembler and debugging kit for PHP, it exposes the necessary API for the development of a debugger in userland. It is an advanced extension of the existing Reflection API, giving it a shallow learning curve for anyone already familiar with Reflection.

While it's annoying that we still must have a binary dependency, I'm hoping that inspector becomes a defacto part of php installations in the not too distant future. Although I have no intention of making an RFC to merge inspector into core - it belongs outside of core, the release cycle in core does not lend itself to new software and there is nothing to be gained by merging. Being a defacto part of installations doesn't necessarily mean merged into core.

Code or STFU

Fig 1. idbg help
This isn't just pipe dreams, the PHP code exists, it's alpha quality and largely untested ...

There is much to do and you shouldn't design your workflow around this (or any alpha quality software) yet.

What you should do is start reading code, testing, and opening pull requests ... consider me waiting ...

Tuesday, 22 May 2018

PHP allows for the design of X

Fig 1. A thing I said
Starting complicated twitter conversations should be avoided, I know this, and yet blurted this out on twitter recently ...

This was met with a flurry of responses and I couldn't reasonably reply in tweet form. I'm going to respond to some of those tweets (indirectly) and further explain my original tweet.

PHP is not always the right tool for the job

First and foremost, I was misunderstood by some people; They thought I was saying you should use PHP for everything. Obviously, that would be an untenable position, which I do not assume.

Give a task to a polyglot and they won't spend time enumerating for possible exclusion all of the languages they know. It doesn't work like that, you don't start thinking about the most unsuitable language for a task and somehow work your way to a suitable language. Choosing a suitable language is a thing you want to call an instinct, but it isn't an instinct, it's guided by an understanding of the task, and prior knowledge of domain support among your chosen poisons ... I mean languages.

There are totally legitimate reasons to choose other languages over PHP, even in the domain where PHP excels - on the web. But it doesn't have very much to do with PHP, and has everything to do with the chosen language and the task. You likely weren't thinking about PHP when you made the decision.

PHP is not a templating language

Whenever someone says "but PHP was designed as a templating language", I almost want to cry.

Who actually cares what PHP was in the year 1997, the number of lines of code from that software left in PHP is minuscule, if there are any present at all.

In the year 2018, we don't even care what PHP 5 was, we don't care about it's shortcomings, because we should not and do not use it.

Today, when we talk about PHP, we are talking about PHP 7 ... here are some actual facts (the things you can't have your own opinions on):
  • PHP 7 is fast
  • PHP 7 is a general purpose scripting language
I'm a C programmer, I spend most of my time writing C, and spend some time at levels below that playing with machine code, JIT compilers and so on. When I say PHP 7 is fast, I mean to say that as a C programmer, it's difficult to write code (of equivalent complexity) as efficient as the code Zend generates in the vast majority of cases. It's also as near as makes no difference impossible to JIT Zend opcodes into machine code and have them be more efficient, the facts of the matter are that the assembly that is generated when Zend is compiled is as efficient as any assembly you could hand craft inline, or generate just in time (that's not a guess, I've personally tried  both hand crafting inline asm and JIT compilation of ze3 opcodes).

Obviously PHP is stuck with one data structure, but it's not just a dumb HashTable in PHP 7 anymore, it's smart and will perform optimally most of the time. The structure of a HashTable and the shortcomings of those structures are less important when our applications are heavily object orientated. Reading/writing/interacting with properties on PHP 7 objects is almost entirely unaffected by those things; Given a warm runtime cache, reading a property from an object consists a relative load (a very simple machine code instruction), there is no ht lookups involved. This is also true of HashTables in some cases (they can behave like C arrays).

PHP allows for the design of X

When a project like AMP shows up on the scene, you can't say "PHP wasn't designed for asynchronous execution", it's a nonsensical statement since PHP is a general purpose language, given that support has emerged in this new domain, as a matter of fact PHP does support it, and not accidentally.

Is the support for this new domain as mature as another language in your arsenal ? I don't know what languages you have, whatever this is not a reason to assume that the people working on AMP, or X, are wasting their time because of some imaginary (and it is mostly imaginary) shortcoming in PHP.

Reddit was recently discussing a GUI extension I wrote; It's very frustrating to hear people who don't really know what PHP is capable of decrying it as a waste of time, or no better than software from 10 years ago.

Almost every extension I write gets the same sort of response: "Just because you can, doesn't mean you should". What they are communicating is "It doesn't matter if you can, you shouldn't", which is somewhere between silly, and harmful.

It really does matter if you can.

When support emerges for a new problem domain, let's be pragmatic and observe that expanding the horizons of PHP in any direction is good for the community that relies on PHP (and maybe PHP alone) to make a living. Let's not rush to take new solutions to production tomorrow, but let's not dismiss anything out of hand because of some imaginary short coming in PHP. 

Ideally, let's find time to learn about the new solution to see if it's useful to us, perhaps try to use it in our prototypes and drafts, and in so doing improve it.

PHP 7, as a matter of fact, is internally designed to bend to the programmers will ...

When support emerges for a new domain, take that as proof that PHP allowed for the design of X.

Monday, 16 April 2018

An Introduction to CQL


Recently I have been working on a CommonMark extension for PHP7. It is based on the reference implementation in C, linking to it rather than re-implementing the spec.

The reference implementation in C is extremely fast, and so the extension has a focus on performance, trying to create PHP objects only when necessary, among other (boring) optimisations.

In C the iterators provided by the reference implementation are extremely fast; It simply doesn't matter that you might have to accept every node in a document when you're working in C.  In a dynamic language like PHP it really does matter, even if the objects representing the nodes are short lived. Again when you access a parent or child node in C, you are just doing pointer arithmetic (hidden behind function calls), it's all simple stuff. When it comes to a dynamic language there is all kinds of baggage attached to the object (and even the read operation itself), additional allocations and other such instructions must be executed before the C pointer can be passed into user land.

While the iterators from the reference implementation are fast, they are not smart - they don't really need to be, as explained. When it comes to inspecting a document (before conversion for example, or for editing), the kind of code you need to write in any language consists of complicated nested loops and or recursive calls, it's long and complicated, and difficult to get right.

Introducing CQL

CQL - CommonMark Query Language is a feature that has been developed alongside the CommonMark PHP extension, which solves some of the problems of iterating through a tree structure in a dynamic language by allowing the user to express as a string how to travel through the document and which nodes to return.

CQL consists of a lexer and parser, a compiler for a small set of instructions, and a virtual machine for executing the instructions.

Syntax

For the real geeks, they can just look at the context free grammar, for the rest of us, a query describes a path through a document:

/firstChild/children

The above query will return the children of the first child node of a tree.

firstChild, lastChild, parent, next, previous, and children are all accepted paths.

children can accept sub queries (but cannot have other paths following it, because think about it ...):
/firstChild/children[ /children ]
The above query will return the children of the children of the first child node of a tree.

children can also accept a constraint:

/firstChild/children(BlockQuote)

The above query will return the children of the first child node of a tree that are BlockQuote objects.

Constraints may be or'd together:

/firstChild/children(BlockQuote|Paragraph)

The above query will return the children of the first child node of a tree that are BlockQuote or Paragraph objects.

Subqueries with constraints can also have subqueries:

/firstChild/children(BlockQuote)[ /children(Paragraph) ]

The above query will return Paragraphs that are children of BlockQuotes that are children of the first child node of a tree.

Constraints and sub queries may be nested ad-absurdum to describe a path to take through the tree. The form of the queries I have used here is for readability only, whitespace is ignored, and content after # is ignored.

Execution

Having lexed and parsed your query into an abstract syntax tree, CQL compiles the AST into discrete instructions for travelling through the tree. We're going to skip over a description of that AST because it's throw away and boring. Let's have a quick look at the result of compiling the AST, the instructions:

Each instruction has an input value (IV), and an output value (RV) or JMP target (#T), in addition it has an extended value (int) for storing constraints, and probably other things in future.

We'll start simple, with /firstChild/lastChild, which compiles to:

For simplicity, you can consider the numbers in IV and RV columns variables, the first instruction FCN sets 1 to the first child node of 0, the second LCN sets 2 to the last child node of 1, and the third instruction ENT dispatches a call to the caller of the function with the address of the node at 2.

Remembering that these "variables" are just addresses, no zvals, no php vars, all very low level stuff.

It gets a little more complicated when it comes to children, /firstChild/children compiles to the following instructions:

The first instruction FCN sets 1 to the first child node of 0, the second instruction sets the first child node of 1 to 2, the third ENT dispatches the enter call. The next instruction NEN sets 3 to the node next to 2 in the tree, the next SET instruction sets 2 to 3, and the next JMP jumps to ENT if 3 is positive, creating a loop until all the children are consumed.

The textual description of a query like:
/children(List)[ /children(Item)[ /children(Paragraph) ] ]
would be extremely boring, but here's what that query looks like:
The only new instruction is CON, which will skip nodes that do not match the constraint given.

The virtual machine that executes the instructions looks like:

Making execution of the query extremely efficient, much more so than you would be able to write in PHP.

PHP API

Proper documentation for the PHP API will become available in the manual soon, here's a quick description for those that want to get started:

The CommonMark extension declares \CommonMark\CQL:
class \CommonMark\CQL {
    public function __construct(string $query);
    public function __invoke(\CommonMark\Node $node, callable $enter);
}

The callable provided $enter should have the prototype:
function (\CommonMark\Node $root, \CommonMark\Node $node)
and will be invoked by CQL on ENT instructions.

Get Involved or Wait :)

I am not finished writing tests for CQL yet, so it currently lives in a feature branch. It will be included in the next release of the extension, probably in the next couple of weeks.

If you feel like being helpful, you could come and submit a PR for tests ...

Peace out phomies ...

Tuesday, 16 January 2018

Sensible Targets

Fig 1. Current release cycle graph
There has been a lot of talk recently about which versions of PHP you should support for your new projects or packages.

As a release manager for PHP, someone who watches the way releases evolve extremely closely, and has some sway over what gets fixed and what doesn't, and as someone who helped to draft the security classification document for PHP; I feel I have some useful things to say on this subject, so here goes ...

The Release Cycle

Every release of PHP goes through the following cycle:

Pre Release:
  • 3 Alpha, two weeks apart
  • 3 Beta, two weeks apart
  • 6 RC, two weeks apart
Release:
  • GA, roughly 6 months after the first alpha
Actively Supported:
  • For two years the PHP team make a patch release every month with bug and security fixes.
Security Only:
  • For the final year of the three year cycle, the PHP team will make a patch release when security fixes warrant a release.

What isn't a security issue ?

We have various definitions to classify the threat level posed by any security issue, but importantly for the community at large, we also have a definition of what is not a security issue:
  • requires invocation of specific code, which may be valid but is obviously malicious
  • requires invocation of functions with specific arguments, which may be valid but are obviously malicious
  • requires specific actions to be performed on the server, which are not commonly performed, or are not commonly permissible for the user (uid) executing PHP
  • requires privileges superior to that of the user (uid) executing PHP
  • requires the use of debugging facilities - ex. xdebug, var_dump
  • requires the use of settings not recommended for production - ex. error reporting to output
  • requires the use of non-standard environment variables - ex. USE_ZEND_ALLOC
  • requires the use of non-standard builds - ex. obscure embedded platform, not commonly used compiler
  • requires the use of code or settings known to be insecure
Any issue that falls under any of the above categories, even though it may have security implications for you personally, is not treated as a security issue. It may be fixed as a normal bug, but that fix will not be included in a security fix only release.

In addition, any security issue classified as having a low threat level will not necessarily be included in a security fix only release. The lowest level of threat is defined thus:
This issue allows theoretical compromise of security, but practical attack is usually impossible or extremely hard due to common practices or limitations that are virtually always present or imposed.
This also includes problems with configuration, documentation, and other non-code parts of the PHP project that may mislead users, or cause them to make their system, or their code less secure.
Issues that can trigger unauthorised actions that do not seem to be useful for any practical attack can also be categorised as low severity.
Security issues, that are present only in unstable branches, belong to this category, too. Any branch that has no stable release, is per se not intended for the production use.
Aside from those bugs which may or may not be a security issue, there is a variety of bugs that are definitely not a security issue, but may cause your project serious harm, or present serious problems for your package - No fix is forthcoming for these, the vast majority of bugs, while the release is in security fix only cycle.

What should I target ?

Targeting a security fix only release of PHP for new projects doesn't make any sense: When a release is in security fix only cycle you should be concentrating on getting old projects upgraded, and a year is plenty of time to do that. In the case of PHP 5.6, we extended the security cycle to two years. If you are reading this and thinking a year isn't long enough to do that, then there is something wrong with the way you deploy or support projects or packages: It has to be long enough, running a version of PHP without active support is dangerous for your business, reputation, and soul.

New projects or packages should obviously target an actively developed version of PHP. At the time of writing both 7.1 and 7.2 are being actively developed (there will always be two versions in active development). Whether you choose to use 7.1 or 7.2 depends on your project or package, perhaps you'd like to use some new features, and not have to worry about security cycle for nearly two years and so can reasonably target 7.2. Perhaps you have reasons to stick with 7.1, and are prepared to deal with security cycle before the year is out.

The bottom line is this: New projects or packages must target an actively developed, fully supported version of PHP.

Wednesday, 8 November 2017

Test Etiquette

Fig 1: A brigade of woobles, apparently
Today, we're going to talk about testfest, in case you have no idea what that is, here is an excerpt from the website:
Have you ever wanted to contribute to PHP but have been afraid that your C skills aren’t up for the challenge? Well, have no fear! If you know PHP, you can contribute by writing tests. Through your local user group, PHP TestFest will show you how.
I've long been trying to propogate the view that you don't need to be a master of anything (including C) to be a valuable contributor to PHP. While the language is written in C, absolutely everything else - tests, websites, admin systems, documentation - is written in languages we all understand; PHP, XML, and Javascript.

Test Fest is focused on turning you into a contributor to php-src by educating you on how to write tests for PHP, but there is lots for everyone to do.

The idea is that you attend local meetups and are guided in the practicalities of writing tests for PHP, with the goal to improve the quality of the test suite that is part of continuous integration and quality control.

I've reviewed nearly all of the pull requests made so far, and approved the vast majority of them. Some of them I'm not able to approve, for a few reasons. First, I want to look at those reasons in the hope that user group organizers and participants will see this information and so reduce the amount of rejection.



Test Coverage

Coverage shouldn't be the primary driver for adding new tests, quality should.

Nevertheless, coverage is a good indicator that you are not duplicating tests - a thing we obviously want to avoid.

There exists a web interface for viewing coverage information for PHP tests at gcov.php.net.

For anyone organizing a meetup, gcov needs to be front and centre: With such a vast number of tests, and already a reasonably high level of duplication we must make sure that coverage is not further duplicated.

For anyone writing tests: It would be helpful, although not necessary, if your pull request linked to gcov (you can only link to whole files, not individual lines) and included the details of the lines (or functions) you are trying to cover. This makes review that much easier, and so probably quicker.

Testing ZPP

ZPP - zend_parse_parameters, is in some form called upon entry to nearly every internal function in PHP. It accepts the number of arguments that were passed, and a specification string describing what the function expects to find on the argument stack. By convention, if the stack does not contain expected arguments, the function or method should return immediately leaving the return value set null (or undefined).

Because this is such a widely used function, it has been tested roughly one squillion times over, and there's not much sense in testing convention.

For anyone organizing a meetup: Please make clear that we don't want to test ZPP.

For anyone writing tests: If you are writing a test and are EXPECT'ing something that matches:
expects parameter %d to be %s, %s given
Then you are testing ZPP, unnecessarily, and while coverage may report an increase, it's improved quality we are looking for.

Clear Intentions

This may seem more subjective, harder to get right, but it's not different to writing normal code: The intention behind any code should be clear. Just as if you find yourself writing long comments in normal code, it may need to be refactored; If you find yourself writing complex and cryptic descriptions probably the test needs to be refactored.



Lastly I want to encourage anyone and everyone to find a local meetup that is participating in testfest and attend, even if it's your first time: All of us depend on the tests that PHP is distributed with, and all of us are qualified to improve the quality of those tests.

Imagery is © 2017 PHP Community Foundation.

Wednesday, 2 November 2016

Expanding Horizons

Fig 1. My view of the horizon this morning.

Recently I have been working on a new extension. It is a wrapper around libui, which is a cross platform user interface development library, that allows the creation of native look and feel interfaces in the environments it supports.

The gravitas of this may not hit you in the face, until you see something like this:


 That's a few hundred lines of PHP 7 code, moulded into an imitation of the snake game we all used to have on our phones.

We've seen other user interface extensions before in PHP, there's even a modified PHP runtime that will allow you to write GTK+ applications.

I don't know anyone that ever deployed any of those extensions, and for very good reasons; PHP5 can barely do anything without allocating a bunch of memory, and doing a bunch of other extremely inefficient things, almost everything it does is inefficient. Beyond a basic forms like application, PHP5 is close to useless.

The snake game runs on my machine using a tiny amount of CPU, and a tiny amount of RAM, while more complex things can take up more resources, they can also achieve very decent frame rates.

PHP 7 is not just fast, it's efficient; It's not unreasonable to expect it to achieve 60 frames per second.

(Note: download the video above from github, streaming it in a browser may not work).

libui is in it's infancy, and is not complete, however there is nothing that is out of bounds for us in PHP, when libui supports it.

The UI extension is documented in the PHP manual, and is already on v2. It will move forward about as quickly as libui.

I'm not a game or UI designer, I don't like to do anything you look at normally.

I wrote this extension to expand our horizons, so that you can create things I cannot imagine ... enjoy it ...

Monday, 26 September 2016

me et mentis morbum

Fig 1. What I aspire to be ...

This morning, I want to talk about mental illness ... and apologize.

The preceding sentence was rewritten 42 times, and contains the words from the first revision.

In some sense, it is difficult to use the words "mental illness" when we are talking about ourselves.

There is a kind of stigma attached to even thinking the words. Before you can think the words, you must first have the revelation that there is something wrong with the way you behave and or feel.

Some or all of the following things happen when I have to mix with other people in real life:
  • I will try to avoid it, completely.
  • I can't remember where I am, or where I am going, and appear and feel lost.
  • I struggle to recognize people, or remember names.
  • I don't move among humans like other humans do; I bump into them in closed spaces (for example, supermarkets) because I can't read their behaviour.
  • I become outwardly awkward, developing ticks (for example blinking), stuttering and repeating myself. 
  • I become inwardly slow, results in not being able to join in conversations properly:
    • Struggle to figure out if I agree or disagree with any statement.
    • Wonder if it is worth saying what I want to say.
    • Wonder if I might be stupid.
    • Fail to form a response before the conversation moved on.
    • Malform a response, with stuttering and repetition abound.
If I become conscious of any of the behaviours above, my physiology changes; I begin to radiate heat and sweat profusely. This always results in my ending it early and just leaving, often without announcing my departure.

There are a few people who make me feel somewhat at ease, just by their presence. People who are physically large (I am rather small), and attentive (go out of their way to patiently interact with me). I can't really explain this, but they seemingly have some immunity.

To compound the problems I have with social or stranger interactions, and possibly even as a result of it; I cannot remember, in any detail, for any appreciable amount of time, what has been said. With the occasional exception where the interaction resulted in a changed or new understanding of something I am interested in, I will normally have forgotten, everything, including the detail of where I was when anything happened, and usually how I got there (having driven, or ridden a motorcycle to the location), by the next day. I retain new technical information, or more generally ideas, usually, sometimes incorrectly. Of course I could be wrong about that, since I don't remember what I don't remember, but it feels that way. In the mundane, I might retain the price of a thing I'm interested in buying, or where to get it from, but may not remember where the information came from. I will eventually have some familiarity with a face, but it takes longer to remember the correct name, and doesn't always happen. I might never remember any particular location, and don't seem to posses the intuition I see others exercising when navigating the world, or even any particular building, or location of a certain size.

That memory problem might sound quite comical, even advantageous given our profession, but it results in a person that may give the first or persistent impression that they can't remember you, your face, your name, if you have children, or are married, or anything else about you. It creates a person that seems incapable of paying attention to other humans, that will deny having even met you, or having had that conversation which you really enjoyed, or I enjoyed.

For most of my professional life, I have been isolated from the real world. Communication with non familial humans has been mostly electronic, and while it may be a tempting explanation to invoke, it's not correct. These symptoms and behaviours pre-date my professional career, some existed as a pre-teen child.

Most of the time, I have a way above average output, not to boast, but I (usually) live to code ... my children have been late for school before (not by much) so I can finish writing or testing a bit of code - because driving to school while thinking about code is, of course, impossible. When I'm given a task, especially one that involves my doing stuff that hasn't been done before, or is exceptionally challenging, it consumes me until it is done. My enthusiasm delivers my above average output.

Twice now, the enthusiasm has been sucked out completely, and replaced by such a strong feeling of dread and worthlessness, that lethargy takes over and prohibits normal function in every area of life.

Many of you will be quick to label this as "burnout": When you can't find the enthusiasm you require to take your kids anywhere, or go to a school event for them, or go shopping for food, or make love to your wife, it is not burnout.

In our technical world, it's all too easy to dismiss behaviours that are symptomatic of mental illness as a product of our geeky-ness, and our working environments. I think this is one of the reasons why these behaviours have been accepted as normal (or normal-for-geeks) and then ignored, even by those closest to me.

The first time the enthusiasm disappeared, life pretty much fell apart, I had no idea what was happening.

I think, I am just recovering (with life intact) from the second time ...

It was extraordinarily difficult to approach my wife, and soul mate of more than a decade, and say out loud "I think I have a mental health problem". They are the words I used, I needed to be direct, unambiguous. By the time I had finished the sentence, I could see the understanding written on her face, the relief ... I'm lucky to have her.

Doctors appointments and diagnosis (acute social anxiety and depression) followed, and treatment is ongoing.

The antecedent factors that lead to these difficulties don't interest me very much,  and are shrouded in the blurriness of my memory whatever. Getting at the reasons seems all but impossible. What concerns me is how to live and function with these symptoms today, not the days or months from my childhood that may or may not have helped to form or exacerbate them.

Compared to the discomfort of telling my wife, telling my manager was easy. My manager has a beard, 
which obviously helps ... while my wife has no beard. In all seriousness, it was only easy because of the understanding nature of the response I received.

I'm not back to normal yet, there are good days and bad, but none of them are normal. I don't fully understand why this has happened, and tend to think it is not fully understandable in principle whatever.

I'm saying all of this in public for two reasons: I think I owe the community an explanation for my recent absence, an absence which may well effect your ability to do your job properly. Most importantly, I feel obliged to speak in order to normalize talking about it, and directly encourage anyone who thinks "that's me" when reading this, to get some help.

Even the internal dialogue that lead to the realization that I have to tell my wife anything at all, was, in some small way, liberating. Surely this helped to provide whatever I needed to first utter those words.

I can't apologize for being unwell, but I can and should apologize if I let you down without explanation; I'm sorry.