MattHicks.com

Programming on the Edge

Showing posts with label comparison. Show all posts
Showing posts with label comparison. Show all posts

Scribe 2.0: Fastest JVM Logger in the World!

Published by Matt Hicks under , , , , , , , , , , on Tuesday, February 06, 2018
An intentionally provocative heading, but one I stand behind until someone can prove otherwise (and I welcome just that).  Scribe 1.x was pretty fast (http://www.matthicks.com/2017/01/logging-performance.html), but was not written with performance in mind.  When I came back around and realized just how fast log4j2 is, I could see no reason why a Scala logging solution shouldn't be able to run circles around it.

Note: the benchmarks below are tested using simple file logging to represent the most common production logging scenario.

Log4J Comparison

Now, for people like me that often want to skip all the blustering, explanations, and bravado, I'll cut straight to the result graph of the performance comparison between log4j 2.10.0 and Scribe 2.0.0:

Like I said, log4j2 is fast, but Scribe 2 is just shy of a 50% performance boost on that.  If we look at the over-time graph it provides additional insights:

You can see that log4j does well, but operations increase in cost partway through, while Scribe is smooth and steady for the entire run.

Method and Line Numbers

This is all compelling but practically speaking, 99% of applications won't even notice the difference between 1,500 nanoseconds and 800 nanoseconds per record logging.  Thus far I've been comparing Apples to Oranges though.  In Scribe, the method and line numbers are integrated into the log records by default.  If we add that to the logging (which any reasonable logging framework should have) we see a different story:

Shocking, right?  If you know Java, you'll probably realize why this is.  In Java, the only way to get access to method and line numbers in your logging is by walking the stack trace.  This is a very expensive operation to be doing and slows the logging to a crawl.  This is why it's not on by default, and why you don't see this talked about much in Java logging frameworks.  However, Scala Macros come to the rescue!  In Scribe, we get all of that for free.  The method and line number information are extracted at compile-time so you can see that Scribe is just as fast whether method and line number logging is enabled or not.

Typesafe Scala Logging

In 1.x my focus was the comparison with Scala Logging.  As you can see below, we're not even in the same ballpark:


It's a pretty pathetic comparison.  In Scribe, 1.x Scribe was noticeably faster, but this shows just how inefficient Scala Logging is.

All Loggers

If you'd like to see the side-by-side comparisons of all the competitors:


Though the log4jTrace and scalaLogging results dwarf the performance distinction between log4j and Scribe, if you've seen all the results here, Scribe is the clear performance winner here.  I'll make another post to show why it's also more powerful, but I'll save that for another day.

Sources

I'm not a master with log4j or Scala Logging, so it's possible I'm not giving ideal running circumstances for these loggers to "show their stuff".  The original source code is posted in the repository: https://github.com/outr/scribe/blob/master/benchmarks/src/main/scala/scribe/benchmark/LoggingSpeedBenchmark.scala

The JMH benchmark results were also saved to a JSON file if you want the raw results to make sure I'm not trying to pull a fast one: https://github.com/outr/scribe/blob/master/work/benchmark/2018.01.31.benchmarks.json

Getting Started

To learn more about Scribe and start using it, check it out here: https://github.com/outr/scribe

Please feel free to email me if you find any mistakes in anything I've said to set me straight, or you can publicly shame me by writing a comment on this post.  I welcome criticism and praise, but criticism gives me something to learn from, so it is more appreciated.

Logging Performance

Published by Matt Hicks under , , , , , , , , , , on Thursday, January 12, 2017
I've never been a fan of the setup of logging frameworks as far back as when I was a Java developer.  The hassle and complexity of configuring and managing the logging framework was always a big hassle and would often create serious problems in the application if not done right.  Even today in Scala it doesn't feel much better.  Certainly we have Macros that give some additional compile-time optimizations, but it's amazing how little has changed.

A while back I created a Scala logging framework called Scribe.  Honestly, the primary reason had more to do with giving greater flexibility to control configuration in code over performance or anything else.  However, by not building on top of log4j, logback, slf4j, or JUL, I found that the system was not only far more simplistic and configurable, but it was also faster.

I recently did a comparison between Lightbend's Scala Logging framework to see how it performs.  Without any additional optimizations the results were pretty impressive.  I configured both Scribe and Scala Logging to avoid writing to standard out as that would be the primary bottleneck of performance and simply wrote a custom Writer / Appender that would simply count the log entries:


Over sixty seconds I recorded how many records could be logged.  Scala Logging was able to log 474k records and Scribe was able to log 610k.  Now, obviously this is far more logging than any reasonable application should be doing, but the point was to prove that not only can Scribe keep up with the most popular Scala logging framework (Scala Logging) on top of the most popular Java logging framework (Logback), but it quite a bit faster.

The second thing I measured was memory consumption over the run.  Memory usage is a very important factor with regard to logging as it should have a very small footprint to give maximum allocation to the application itself.  Again, my finding were pretty strongly in favor of Scribe:

While Scala Logging utilized 704kb of memory Scribe utilized on 596kb.  Again, not a substantial difference when we're discussing hundreds of thousands of records being logged, but this is meant to prove that Scribe is the better performer.

Very often I hear that a developer won't use a framework because there aren't enough developers using it.  Obviously this creates a chicken / egg situation as you can't get developers using it because not enough developers use it.

Hopefully this short post will give some additionally credibility to the value of Scribe that people will start comparing features and see just how much it has to offer.  If there's something missing that your existing logging framework has, just create a ticket.

Play Framework for Scala: An Evaluation

Published by Matt Hicks under , , , , , , , , , , , , on Friday, June 03, 2016
I often speak to clients and developers that are pushing the Play Framework as the ideal web framework when developing Scala web applications.  I started considering why Play is the framework that people tend to settle on, especially large companies.  I think there are a few reasons:

  1. It's supported by Typesafe *cough*, I mean Lightbend. Certainly Lightbend is the main company supporting Scala and to many people that means you should use whatever technology they are pushing.
  2. It has commercial support. This is a bleed-over from point #1, but I think warrants its own point.  Especially for big companies having the ability to get commercial support is very important.  It is unfortunate that truly open-source projects that are entirely community driven are seen as riskier, but typically that is the mentality.
  3. Play is actively maintained. It has been around for years and is sure to be around and maintained for many to come. Having a long history seems to give a lot of credibility to frameworks whether they deserve it or not.
  4. It's huge! There are a ton of modules and features that Play has available for your various needs and that provides a compelling option to companies that want to grow and expand and may need those nifty features in the future.
  5. Easy to get going. The handy-dandy Activator makes creating and managing your application stupid simple (with an emphasis on "stupid").  Especially for people building initial prototypes and evaluating the options available often find this compelling.  Activator helps get them going fast without much fussing with the build tools or framework.
  6. Big companies use it so it must be good! LinkedIn and the Guardian use it and certainly others, so it must be a good choice, right?
These are all important and mostly valid points, but for a developer that has created many web frameworks over the years and has built his fair share of web applications most of these points are not as valid as it might seem on the surface.  I'll attempt to address each of them and hopefully give some insight into why I think Play Framework is not the right tool for the job and no matter what you are writing in Scala there are better options available.
  1. Lightbend backing the framework is definitely a solid point in favor of the framework, but it doesn't mean it's the best framework for Scala. For example, Lightbend also supports Slick, but there are serious performance problems in that framework which led me to create ScalaRelational.  For an overview of the crazy performance distinctions between the two frameworks see here (this just scratches the surface, there are simple queries that should take milliseconds to complete that take minutes and up to hours to run).
  2. Though perhaps one of the most compelling points in favor of Play Framework, commercial support doesn't mean the primary active development on any "supported" framework by Lightbend is being done by Lightbend.  These are primarily open-source frameworks that Lightbend has taken it upon themselves to commercially support and most of the actual development is still being done by the open-source community.
  3. Actively maintained is a very good sign in any framework.  Not actively maintained frameworks are incredibly risky unless they have a specific function and aren't currently being maintained because they fulfill that function well and don't need further development.  For a web framework that's certainly not the case.  The Spring Framework for Java is still actively maintained, but it's a monolithic and painful platform that inspired self-loathing and hate.  Many projects start off good or at least good intentioned only to eventually expand themselves into something that has long since lost the focus and benefits of its original intent.  I wouldn't say Play has gotten as bad as Spring, but once you get past the dead-simple getting started tutorial, the nitty-gritty of the framework starts to seep into your bones causing maintenance and maintainability nightmares.
  4. Though having support for the various features you may eventually need built as modules to your framework is very nice, it also often results in the framework itself trying to solve too many problems and ending up solving nothing very well.  I try to focus on using frameworks that specifically focused to a specific problem and solve that problem well.  When a framework tries to solve too many problems it starts making compromises and watering down the overall benefits of the framework.
  5. Oh Activator, how I loathe thee!  I'm sure it seemed like a good idea to create a shiny wrapper around SBT to help create your project, run it, and even deploy it without being bothered with understanding how building your Scala project actually works.  However, it's when you need to manually do something and you realize you don't have a clue how the stupid thing works that it becomes a maintenance nightmare.  I'm a software developer, and software developers should be smart enough to create a new project from scratch without needing a tool to hold your hand.  If you aren't smart enough to create your build from scratch then you're either an idiot, or the tools are far too complicated.  Instead of dumbing down the complex tools by wrapping it, why not attempt to solve the problem by making the tools themselves less painful to learn?  Yes, I'm talking to you SBT!  What used to be Simple Build Tool has had to change its name to stop the laughter in derision (now Scala Build Tool).  SBT has definitely improved recently, but there is still far too much complexity to manage and maintain.
  6. Big companies make stupid decisions constantly.  Web frameworks are one the primary areas in which they make stupid mistakes.  You may argue, "but their site works, so it must have been the right choice", but take a look at Facebook's architectural history and you'll see a good example of sheer stupidity leading down a path of pain and the only way they could stay afloat was due to their popularity they could keep throwing money at it.  Don't use big business as an example of what you should do.  Most companies can't just keep throwing money at a solution until it works, and even ones that can't would be better off spending that money on other things and keep their programmers sane.  I've worked for and more recently have consulted for lots of big businesses and even for the US government (the biggest and most wasteful business in the world).  I try to avoid consulting for big companies when I can now for this very reason.
These points hopefully address at least the primary reasons many people choose Play Framework, but the answers themselves aren't evidence of why it shouldn't be used, they are simply responses to the common reasoning I hear.  My specific reasons why I try to avoid Play are a bit different:
  1. Templates with their own dialect and learning curve and injecting code directly within.  This is just wrong on so many levels.  The time it takes to learn Play's specific template dialect is problematic, the injection of code in your templates make things incredibly messy, and don't get me started on the nightmare of trying to refactor code.
  2. Play Project Structure. Why? Seriously! There is no logical reason to break from the standard of normal Scala projects "src/main/scala" to the mess that is Play's arbitrary and rigid project structure.  Not only does this further increase the learning curve, but it makes your code very different from every other Scala project.  Again, why?  There is no explicit gain from their mediocre project structure changes, and in the latest version you can override it, but it says it's "experimental" and might cause problems.
  3. Routes file.  Again, why?  It's a freakin' text file that compiles to Scala.  It's unfortunate that Scala doesn't have a powerful DSL that would make more sense than writing a text file...oh wait, it does!  I have spent a great deal of time contemplating this and I really have no idea why they would do this.  If we were talking about a configuration file that could be changed in production without rebuilding your project that would be one thing, but the routes file is compiled and built into your project.
  4. Performance is bad.  Six months ago I was working on a project and they were experiencing serious performance issues in their web services.  They were using Play and PlayJSON.  After a little bit of testing I found that the major bottleneck was Play.  I quickly swapped out for Spray and uPickle and the performance was then lightning fast, it was fewer lines of code, and the code was much clearer and easier to maintain.  Now, I can't generically defend that Play's performance is always bad, and it's possible in the latest releases that it is no longer an issue at all, but the framework has been around for years and there is just no excuse for serious performance issues like that making it into the code.
  5. Distraction from simplicity.  When I work on a project my mantra is, "make it as simple as possible, no more and no less".  Developers working on projects have a tendency to over-complicate things and especially among Scala developers attempt to be clever and end up creating a maintenance nightmare for themselves.  Developers also focus too much on simplicity and leave glaring holes in functionality or paint themselves into a corner that they can't code themselves out of.  A project should be as simple as possible while keeping in mind the overarching goals and a consideration of where the project is going.  Play is not a very flexible framework and when you need to diverge for business needs they make it painful to do so.
Wow, I got through an entire post without writing any code.  I think this is a first.  In summary, yes, I've spewed a lot of hatred towards Play Framework, and though most of it is justified, it is not a horrible framework.  I think there are better frameworks like Scala.js, Spray, Finagle, and possibly even Akka-HTTP now if they've resolved some of the missing features and performance problems.  I know it's a Java framework, but I've also been pretty impressed with Undertow.

Play Framework developers: If you read this, I apologize for the harshness, but hopefully this can be taken as constructive criticism and I would happily recant in a future post.

case class Scala

Published by Matt Hicks under , , , , , , , on Tuesday, February 19, 2013

I've been pretty busy the past few weeks with clients and haven't had much time to blog. Last week, however, I gave a presentation to the OKC JUG (Java Users Group) about Scala. As anyone that actually reads my blog must know, Scala is my primary language and I absolutely love it. This week since I don't have a lot of time to delve into anything complex I'll simply share my presentation slides comparing Scala and Java code:

It is amazing how much more simplistic tasks can be accomplished in Scala versus Java.

Hyperscala: Why not Play?

Published by Matt Hicks under , , , , , , , , , , , on Wednesday, January 30, 2013

This article is continuing in the series on exploring Hyperscala. If you have not already done so, I would highly recommend reading the following previous posts as many topics discussed here build on concepts previously discussed:

The Play Framework is perhaps the most popular web framework among Scala developers today. I have been asked quite a few times what is wrong with Play that made me decide against using it and instead write my own web framework. To be fair, Play is a pretty awesome framework and is a great choice for web applications. However, there are a few problems I have with it that led me to choose against using it moving forward:

Templating Language
Though Play does a far better job of this than pretty much anyone else I've seen, you're still dealing with special syntax in your HTML templates for accessing your Scala code. This is incredibly problematic when there is a separation of designer and programmer. Life becomes quickly more difficult when the programmer injects all the Play-specific code into the HTML file that came from the designer and then the designer needs to make a change. Not only does it become difficult for the designer to even preview what the content should look like now, but it is highly likely that the designer will mess something up when they are trying to make changes to the HTML. This was something I spent a lot of time considering and trying to come up with a better solution for in Hyperscala. I have worked at a lot of large companies that have teams of designers and teams of developers and it is incredibly painful bridging that gap. In Hyperscala there are actually several solutions to this problem, but the best one for this specific scenario, I believe, is DynamicContent. We've discussed this in a previous post and demonstrated it in yet another post. The idea is keeping the HTML clean and pure and the developer simply loads in only what they need to manipulate by the HTML 'id'. In my opinion, this is the simplest solution and a much cleaner separation between the designer and the developer.
Modularity
Yes, there is module support in Play, but it is confusing at best and extremely limited at worst. There is an inherent problem in any framework that doesn't have complete control over the HTML and Play simply does not. The way Play works is very similar to JSPs where content is injected but the HTML is never parsed or comprehended. This leads to several problems when you have modules that need to introduce something like jQuery but shouldn't load it multiple times and want to avoid an issue where another module is trying to load a different version. These are complicated issues that need to be dealt with in large web applications. In Hyperscala the Module system is incredibly powerful and solves all of these problems incredibly well. Not only that, but a Module in Hyperscala is dead simple to write and even more simple to use.
Complicated Setup
Any framework that needs its own console in order to create an application is too complicated. Yes, I agree that it's cool that the Play framework has its handy-dandy console utility to create your application for you, setup your IDE, and probably even brush your teeth for you. However, I very much dislike "magic" that happens and is unexplained. I prefer to understand what is going on under the hood and though you can do this in Play, the decision was made as a default route to hide this from the developer. I prefer to work with frameworks in which you add a Maven dependency and then start writing some code. I don't want configuration files. I don't want a bunch of boilerplate code that is generated on my behalf. I want to instantiate something and run it. This is exactly what Hyperscala does. Once you include your Maven dependencies for Hyperscala you need only create an implementation of Website and add a Webpage to be up and running. In Play you have a minimum expectation of an Application.scala, index.scala.html, application.conf, and routes file.

In an effort to compare Hyperscala with Play practically I decided to take an example from Play and re-write it in Hyperscala. My hope was for a simple 'Hello World' example to keep it simple and straight-forward, but what Play considers their 'Hello World' example is quite a bit more than that. It will have to do.

First lets take a look at the Application.scala file:

This is fairly simple. The idea is that this page asks you for your name to display, the number of times to repeat it, and a color. When you hit submit, it validates the form (based on the validations specified near the top of the page) and then either displays errors or writes out the name you specified the number of times you specified in the color you specified. Notice here that the form validation process is hard-coded, so no special handling is necessary. I point this out now because in Hyperscala there is no "default" for how validation should be handled so it takes a little more code (but not much).

Next we take a look at the HTML files defined for the display.

hello.scala.html index.scala.html main.scala.html

It's fairly clean and I'm sure once you get used to the Play syntax it becomes easier to grasp. However, this would be quite difficult for a designer to work with. I'm sure there is a better way to represent the page for designers, but then you obviously lose out on much of the power of Play.

Now lets take a look at how this same functionality would look in Hyperscala. Like I've said several times now, there are many ways to accomplish the same task in Hyperscala and this is just one way.

First lets look at the HTML, since this is what we really should start developing from. We can focus on getting the design exactly how we want it before we even think about Hyperscala:

play_hello_world.html

This is our basic HTML for the page. Notice there is absolutely nothing specific to Hyperscala or non-HTML in the file at all.

play_hello_world_configuration.html

I've extracted the 'configure' page out into this snippet because we're not only going to replicate Play's Hello World example, but we're going to leverage the Realtime module of Hyperscala to avoid doing a POST and thus keep you on the same page for the entire experience. I could have replicated the form posting utilizing FormSupport mixin, but hopefully this will work as a good example of how easy real-time communication is in Hyperscala. Again, notice that there's nothing special about this HTML. It can easily be previewed in the browser and edited by a designer.

Now, lets take a look at our Scala code:

PlayHelloWorldPage.scala PlayHelloWorldConfiguration

Not much to see that hasn't already been explained in past examples but there are a few things of note. First, notice the call to Realtime.connectStandard(). This, as the scaladocs says, connects all inputs, textareas, and selects to fire change events and buttons to fire click events to the server. We can do this manually, but this saves us a few lines of code. The other thing of note here is the adding of validation. The 'addValidation' method is received as an implicit conversion on FormFields (input, textarea, and select) by importing org.hyperscala.ui.validation._. We utilize some built-in validations and use the ClassValidationsHandler to apply the error class to the outer container and set the message to the error container when validation fails on a field. Like I said before, how validation works in Hyperscala is not built-in, it's part of the UI sub-project and defines some convenience functionality of how error might be handled, but opens the door to supporting validation errors any way you see fit.

In conclusion, I would argue that while in this example the lines of code may be equivalent, the benefits should be seen particularly for larger applications and for interaction with designers. I do not want this to come off as me bashing Play Framework. I have nothing but respect for the framework and the developers that created and use it. My purpose in this post is merely to compare and contrast the architectural choices in one framework against another and to hopefully better explain why I believe Hyperscala to be a better framework in many situations.

Source code referenced for the Play Hello World example came from Play samples on github:

Source code referenced for the Hyperscala comparison came from Hyperscala examples on github: