xrDebug 3.0

Go xrDebug!

rodber
rodber   GitHub

For xrDebug V3 I have rebuilt the software from PHP to Golang. This major update brings enhanced performance, reliability, and cross-platform support with binary builds available for Windows, macOS, Linux, and FreeBSD. The source code is available at xrdebug/xrdebug on GitHub.

In this post, I want to share the challenges faced with the PHP version, the transition process, and the significant improvements achieved with this new release.

# Based, PHP xrDebug

Initially, xrDebug was developed as an all-in-one PHP client-server system. I chose PHP because of its flexibility and simplicity, given my long experience with the language. PHP has always been a go-to for web-related tasks, and it felt natural to build xrDebug with it.

The PHP ecosystem is diverse, and it wasn’t a challenge to build a debug server based on SSE, distributed in binary form, thanks to existing libraries for it. However, binary distribution was limited to macOS and Linux. While Ray offered a Windows installer, this created a disadvantage for xrDebug, which required users to run WSL as a workaround. This was a significant drawback, limiting access to the software for a large portion of the potential user base.

I focused on the project distribution goals, and though PHP is a powerful and versatile language, I ultimately determined that creating reliable, cross-platform distributable desktop software was better suited to a different technology stack.

# Golang xrDebug

I chose Golang for its cross-compilation capabilities and robust standard library. During the rebuilding process, I aimed to minimize the use of third-party libraries, relying instead on the language itself as part of my learning journey. Keeping the project simple was a priority, and Golang was the perfect fit.

The ability to cross-compile Go code for multiple platforms was a game changer. With just a few commands, I could generate binary builds for each platform, ensuring broad compatibility and accessibility for users. Integrating cross-compilation into GitHub Actions was straightforward, allowing the CI/CD pipeline to be set up quickly and efficiently.

Golang’s comprehensive standard library, which includes support for HTTP, testing, benchmarking, linting, and a language server, provided a robust foundation for development. It felt great to have everything I needed right out of the box, without relying on external dependencies or complex IDE configurations. I’m used to having my own tooling and custom setup, but with Golang, none of these were necessary, making it a refreshing experience.

# Improvements & new features

The transition to Golang brought several key improvements xrDebug. Here are some of the highlights:

# Cross-platform support

The transition to Golang has enabled cross-platform compatibility. Users can now download and run xrDebug on their preferred operating system without any additional setup or dependencies, making it accessible to a wider range of developers and users.

# Building improvements

Release times for both versions are similar, around one and a half minutes. However, Golang produces 8 binary artifacts, twice as many as the PHP version, in the same time. The key advantage is that the build process with Golang is simpler.

Here’s the Golang workflow and the PHP version. Notice that the PHP version requires more setup, making the project more complex and harder to maintain.

The compiled binaries are significantly smaller in size: previously around 30 MB, now just 10 MB. The Docker image size has also reduced from 148 MB to 10 MB. The package size (tar.gz) is now about 4 MB.

These improvements in distribution and resource consumption make xrDebug more lightweight and efficient. The reduced binary and Docker image sizes enhance portability, allowing developers to integrate xrDebug into their workflows without excessive resource usage. This portability is crucial for developers who need to run debugging tools in various environments, from local machines to cloud-based systems, ensuring a seamless and efficient debugging experience.

# Dependencies improvements

The PHP-based version of xrDebug relied on several external dependencies to achieve its functionality. While the PHP ecosystem provides a rich set of tools and libraries, managing multiple dependencies can increase maintenance overhead and complexity. As the saying goes, "a dependency is a liability."

In contrast, the new Golang-based version significantly reduces dependencies, relying on just one major external library: the go-cache library, used for the pause lock system.

Golang’s robust standard library and built-in features allowed me to minimize external dependencies, simplifying the project and making it easier to maintain, build, and distribute efficiently. I didn’t miss any of the dependencies I had on PHP, as Golang provided everything I needed out of the box except for the TTL cache system.

# Performance improvements

A significant side effect of transitioning to Golang was a performance boost. The new version is faster, more responsive, and more efficient than its PHP-based predecessor. The optimized concurrency model, efficient resource management, and architecture contribute to the improved performance.

To illustrate the performance improvements, I conducted a load test using wrk by sending 100 concurrent POST requests for 30 seconds to the /messages endpoint with a dump payload. Tests were conducted on the same machine with the same configuration.

Results for xrdebug-php:

wrk -t4 -c100 -d30s -s test.lua http://127.0.0.1:27420/messages
Running 30s test @ http://127.0.0.1:27420/messages
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    17.45ms   10.61ms 330.84ms   94.49%
    Req/Sec     1.49k   232.96     1.99k    75.75%
  178678 requests in 30.04s, 18.57MB read
Requests/sec:   5948.48
Transfer/sec:    633.19KB

Results for xrdebug (Golang):

❯ wrk -t4 -c100 -d30s -s test.lua http://127.0.0.1:27420/messages
Running 30s test @ http://127.0.0.1:27420/messages
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.69ms    5.04ms  85.05ms   91.18%
    Req/Sec    20.89k     3.44k   28.51k    69.00%
  2496773 requests in 30.04s, 428.60MB read
Requests/sec:  83104.24
Transfer/sec:     14.27MB

Summary of results:

  • Go handles approximately 14x more requests per second than PHP.
  • Go exhibits significantly lower latency (about 6.5x less) compared to PHP.
  • Go achieves a much higher transfer rate, about 22x greater than PHP.
  • Go processed significantly more requests and data during the same time frame.

These performance improvements were a natural outcome of transitioning to Golang, with no manual optimizations required. The results were well received, as I anticipated better performance but not with such minimal effort. While the PHP version handled around 6,000 requests per second, which is impressive for a PHP application, the Golang version’s performance was on a different level.

# New features and changes

In addition to the transition to a new programming language, xrDebug 3 introduces several key updates, improvements, and features:

  • Updated signature algorithm: The previous algorithm (based on PHP serialize) has been replaced with a more universal approach, making the sign process available for more languages by simply concatenating keys and values.
  • Updated keys file handling: The new version reads keys from files, not inline.
  • Enhanced logging system: The logging mechanism has been refined, offering more detailed insights and improved error handling.
  • Removed custom working directory: Support for custom working directories has been dropped.
  • Removed CLI color support: Color support has been removed, as it was deemed unnecessary for the current version. The user interface is the SPA, not the terminal.
  • Removed open browser function: The function to automatically open a browser window has been removed.

# Development journey

Learning Golang was an exciting and rewarding challenge, and I want to share some resources that truly helped me during the 15-day journey from zero to a working xrDebug 3.0:

I began with the Getting Started guide, which provided a solid introduction to the language. However, what really accelerated my progress was this video by Alex Mux. In just about forty minutes, it covered the essentials of Golang, giving me the confidence to dive deeper into the language.

Coming from a PHP background, I found “Encountering Go as a PHP Developer” by Daniel Leech particularly helpful. It bridged the gap between familiar PHP concepts and Go’s unique features, saving me a lot of time and frustration. I’m truly grateful to Daniel for sharing his insights, which made the transition smoother.

Setting up Golang with Visual Studio Code was straightforward, and the language support is fantastic. The official extension installs additional tools automatically, making the development environment nearly effortless.

# Closing thoughts

Rebuilding a working system is always a last resort, and that was the case for xrDebug. The transition from PHP to Golang was a significant undertaking, but the benefits far outweigh the challenges. The new version is faster, more reliable and easier to distribute.

Taking the time to learn a new language and apply it to a real-world project has been incredibly rewarding. While rebuilding wasn’t strictly necessary, the journey was worth every moment. It has not only improved xrDebug but also expanded my skills and knowledge.

I’m excited to see how the community receives this new release and look forward to your feedback. Your support and insights will be invaluable as we continue to evolve and improve xrDebug.

Rodolfo blogging since 2012.