A speed comparison between web grids for ASP.NET

When creating web apps, the responsiveness of your app should be priority 1, 2, and 3. If your app spends a minute to load on your CEO’s iPhone, you might as well ask him to carry around the app’s source code, written out on paper. Hence, having accurate data before starting your project, is key to your success  -  And since the most commonly used UI element is probably “the grid”, or “data grid”, I thought I’d write up a speed comparison in the tooling space which is relevant for you when creating ASP.NET web apps.

Telerik KendoUI grid for jQuery

Telerik is one of the largest web component vendors on the ASP.NET stack. They employ thousands of developers, and their components have all the features you can dream of. As always, you pay for what you don’t use, and the specific cost for the Telerik KendoUI grid is exactly 1.4MB of JavaScript, according to their example page. This implies that if you’re trying to consume their grid on a low bandwidth connection, on for instance your phone or something, on an empty cache  -  You can expect to require minutes to load your page initially. On my 50Mb connection the time it takes to simply load their example page, which contains no more than 91 items for the record, is a staggering 7.63 seconds.

Infragistics ASP.NET Data Grid

The “Multi-Column Footers” example from Infragistics, that you can find here, requires a total of 1.3MB of JavaScript. It spends roughly 8 seconds to load on my 50Mb connection, on an empty cache. Yet again, the Infragistics Data Grid has all the features you can imagine, and yet again you pay a staggering price for things you’d highly likely never use. But its feature set is pretty amazing, which allows you to “Filter excel style”, having “Mult-column footers”, “Multi-Column Headers”, etc, etc, etc …

It seems the only thing this thing cannot do, besides from splitting atoms, is to actually have it load on your page, before your users falls asleep. The “wait cursor” is its most frequently seen UI element, as it was with Telerik too.

ExtJS grid

This grid component is in its own category to some extent, since it’s not an ASP.NET datagrid, but rather a generic JavaScript component for any backend you might want to use. However, since it’s so popular in usage, I wanted to include it here none the less. Sencha does not have an example page though, which only illustrates the usage of their grid  –  However, since they often tend to encourage their users to package all of their JavaScript components into a single file, their own usage example is still quite relevant. 1.1MB of JavaScript and 3.5 seconds to load on an empty cache, yet again on a 50Mb connection, which is highly unlikely available on your phone, as you’re waiting for the train, to go to work, and you need to check up when the next train is due …

Phosphorus Five datagrid

This grid is special. First of all, I am its author and creator, so I am probably biased  –  Secondly, it builds upon a unique model of “Managed JavaScript”, which among other things implies that it never downloads more than 4.8KB of JavaScript. It is also the only example that actually uses a “serious dataset”, with more than 315,000 records. Telerik, Infragistics, and ExtJS’ examples pages have somewhere between 100 and 300 records  –  Which makes you wonder if they even work with “real data”. The video below illustrates 315,002 records in its Camphora Five generated app. The initial page load is 4.8KB of JavaScript, and hence arguably more than 200x faster to load than any of the above components. Although I am testing this on localhost, not having an example server to run it in  –  I think the numbers of 4.8KB of JavaScript speaks for itself …

The code necessary to create a grid

Another important fact when creating web apps, is how much time a developer needs to spend to actually implement his application. For Telerik, Infragistics, and ExtJS  -  This implies thousands of lines of code, in 3–4 different languages, in dozens of different source code files. In addition to that you’ll need to learn JavaScript, CSS, jQuery, the component API/Framework, etc, etc, etc. Since I don’t know any ways to illustrate this, since developers tends to not believe me when explain it to them  -  I am compelled to illustrate how to create a data grid in Phosphorus Five using a video …

Summing up

As I said above, I am biased, being the creator of Phosphorus Five  –  However, you can create, consume, and deploy a web app with Phosphorus Five, with a data grid, allowing you to sort and filter hundreds of thousands of records, in milliseconds  –  And you can create your solution 100,000x faster, it will perform roughly 200x better, and you can put real data in it, and not simply tiny sample data of some few hundred records  –  And it simply works …

and you can do it in 2 minutes!

But Telerik, Infragistics, and ExtJS have really beautiful grids  -  I’ll give them that. If you want to build a working app though, with real data though …

you can download Phosphorus Five here (it’s Open Source).

Advertisements

Telerik Kendo UI grid 7 seconds, Camphora Five MySQL grid 0.5 seconds

On my 50Mb internet connection, the examples for the Telerik Kendo UI grid component needs 7.28 seconds to load on an empty cache. My Camphora Five generated MySQL datagrid, with real Ajax, and 315,000 records in its database, needs 0.5 seconds to load on an empty cache. Telerik’s Kendo UI example grid has 91 records in its example. I imported 315,000 records into my Camphora generated app, and still it performs 14 times faster.

If you know anything about web development, you know that size matters. And the smaller things are, the better things are. The reason why Telerik is slow like syrup, while the Camphora Five version is blistering fast, is of course because Telerik needs to download 1,400KB of JavaScript, while the Camphora datagrid only needs to download 5KB. This implies that in regards to bandwidth usage, only counting JavaScript, Telerik’s Kendo UI grid will require 280 times as much bandwidth as the Camphora grid.

Another crucial point in this, is that the Telerik example requires that you write hundreds, if not thousands of lines of code to get it to work – Still it doesn’t use a “real database”. The Camphora Five datagrid was automatically generated in 2 minutes. See how below …

If you want to test my claims yourself, or reproduce the above to comparison, you can download the Open Source code for Phosphorus Five here.

Creating your own Ajax datagrid in Hyperlambda using Micro 2

In the following youtube video, I am demonstrating the “opposite” of what I demonstrated in my previous blog. This time, instead of overriding the databind Active Event, I polymorphistically override the actual extension widget itself.

This allows me to declare my columns without repeating myself, while still being able to inject my own custom widgets in its column headers.

The code can be found below the video.

First run the following code through your System42’s executor.

create-event:micro.samples.widgets.grid-1

  /*
   * Used to separated arguments from the rest of our lambda object.
   */
  .signal

  /*
   * Adding [rows] into [micro.widgets.grid] invocation.
   */
  add:x:/../*/micro.widgets.grid
    src:x:/@.signal/--/rows

  /*
   * Looping through each [columns] specified, and creating a
   * link-button out of each header cell.
   */
  for-each:x:/@.signal/--/columns/*
    add:x:/../*/micro.widgets.grid/*/columns
      src:x:/@_dp/#?name
    eval-x:x:/+/**/a/*/innerValue
    add:x:/../*/micro.widgets.grid/*/columns/0/-
      src
        widgets
          a
            href:#
            role:button
            innerValue:x:/@_dp/#?name
            onclick
              create-widgets
                micro.widgets.modal:my-modal
                  class:micro-modal
                  widgets
                    h3
                      innerValue:You clicked a column header
                    p
                      innerValue:Implement sorting here ...
                    div
                      class:right
                      widgets
                        button
                          innerValue:Close
                          onclick
                            delete-widget:my-modal

  /*
   * Invoking "mother event" and returning results.
   */
  micro.widgets.grid:x:/../*/_arg?value
    columns
  add:x:/+
    src:x:/@micro.widgets.grid/*
  return

Then create a new lambda page in your CMS, and make sure you set its “template” settings to “empty”, and paste in the following code.

create-widget
  class:container
  oninit
    p5.web.include-css-file:@MICRO/media/main.css
    p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
  widgets
    div
      class:row
      widgets
        div
          class:col bg shaded rounded
          widgets
            micro.samples.widgets.grid-1:my-grid
              columns
                Name
                Email
                Phone
              rows
                item
                  Name:Thomas Hansen
                  Email:thomas@gaiasoul.com
                  Phone:90909090
                item
                  Name:John Doe
                  Email:john@doe.com
                  Phone:91919191

It is easy to dismiss Hyperlambda as being a not “real” programming language, because of its lack of traditional OOP mechanisms. However, as you can clearly see above, even polymorphistically overriding existing Active Events, is still easily accomplished, allowing you to reuse pre-existing functionality.

In fact, arguably the inheritance and polymorphism mechanisms in Hyperlambda, are far superior to polymorphism in traditional class based OOP programming languages – Because it makes the Liskov Substitution Principle (LSP) obsolete.

Creating your own Ajax datagrid in Hyperlambda using Micro

In the video below, I am demonstrating how you could extend [micro.widgets.grid.databind] to create your own datagrid, yet still utilise all the existing features from the core Micro components. The code can be found below the video.

Unless you want to create your own column types, you don’t actually need to extend the [micro.widgets.grid] extension widget itself, but you can actually get away with only extending the databind event instead. This allows you to build a specialised “datagrid”, where you instead of relying upon the default behaviour of the grid, can create the cells of your grid exactly as you see fit. Which of course keeps your code very “DRY”. Here’s a screenshot of how our datagrid will end up looking like.

Then a screenshot of what happens as you click any of its cells.

To understand how we built it, feel free to watch the following 4 minutes long video.

Realise that we created the above specialised grid with 61 lines of code, and to consume it is a handful of lines of code. Below you can find the code for creating our databind Active Event first. Evaluate the following code in System42’s executor first.

create-event:micro.samples.widgets.grid-1.databind

  /*
   * Used to separate arguments from the rest of our lambda.
   */
  .signal

  /*
   * Adding items according to how they were defined.
   * Making sure the items becomes possible to edit, by
   * tossing up a modal widget, with a wizard form when cell is clicked.
   */
  for-each:x:/@.signal/--/<-(!/_arg)
    add:x:/../*/micro.widgets.grid.databind
      src:item
    for-each:x:/@_dp/#/*
      add:x:/../*/micro.widgets.grid.databind/0/-
        src:x:/@_dp/#
      eval-x:x:/+/**/a/*/innerValue
      add:x:/../*/micro.widgets.grid.databind/0/-/0/-
        src
          widgets
            a
              href:#
              role:button
              innerValue:x:/@_dp/#?value
              onclick
                eval-x:x:/+/**/_anchor
                create-widgets

                  // Creating a modal widget.
                  micro.widgets.modal:my-modal
                    class:micro-modal
                    widgets
                      h3
                        innerValue:Edit item

                      // Adding a wizard form.
                      micro.widgets.wizard-form:my-form
                        text:new-value
                          oninit
                            micro.page.set-focus:x:/../*/_event?value
                          info:New value
                      div
                        class:right
                        widgets
                          button
                            innerValue:Save
                            onclick

                              // Serializing wizard form, and updating cell's content.
                              micro.form.serialize:my-form
                              delete-widget:my-modal
                              _anchor:x:/../*/_event?value
                              set-widget-property:x:/@_anchor?value
                                innerValue:x:/@micro.form.serialize/*?value

  /*
   * Invoking "mother" event.
   */
  micro.widgets.grid.databind:x:/../*/_arg?value

Then create a lambda page in System42’s CMS, and make sure you set its “template” settings to “empty”, before you paste in the following code.

create-widget
  class:container
  oninit
    p5.web.include-css-file:@MICRO/media/main.css
    p5.web.include-css-file:@MICRO/media/skins/serious.css
  widgets
    div
      class:row
      widgets
        div
          class:col bg shaded rounded
          widgets
            micro.widgets.grid:my-grid
              columns
                Name
                Email
                Phone
              oninit
                micro.samples.widgets.grid-1.databind:my-grid
                  item
                    Name:Thomas Hansen
                    Email:thomas@gaiasoul.com
                    Phone:90909090
                  item
                    Name:John Doe
                    Email:john@doe.com
                    Phone:91919191

By extending the existing databind event in Micro for the [micro.widgets.grid] extension widget, we are able to create our own “custom datagrids”, which allows us to databind our grid with simple data-statements, that will still create a complex widget hierarchy for us.

This allows us to avoid repetition, and our code becomes what’s often referred to as “DRY” – Don’t Repeat Yourselves. In lates blogs, I will demonstrate how to extend the actual grid, to make sure it has specialised columns, that can for instance be clicked, etc.

Creating a million Ajax datagrids in 20 minutes – Aphrodite KISS

Most Ajax libraries with respect for themselves have a datagrid component. And therein lies the problem; *A DATAGRID COMPONENT*! It doesn’t matter how flexible and configurable these datagrids are. Regardless of how many parameters you can modify, there is still some minute feature lacking, which you can’t create, and which you’d like to create for some reasons.

Micro is different, since it instead of having a datagrid, features a “generic grid”, which simply allows you to create an HTML table element, from where you can modify every single aspect of it yourself, and extend it, to end up with the exact specific datagrid as you need. This feature of Micro, is as far as I know completely unique to Micro (and Phosphorus Five). It basically allows you to create any HTML/DOM structure you wish, while still having the grid help you put things into the correct “tbody”, “tr”, etc, elements on your page.

In the video below, I am walking through the most important features of the [micro.widgets.grid] extension widget from the latest v3.2 Aphrodite release. First watch the viddi, then scroll down on page to find the code I am using.

First example, statically creating items during creation of grid.

p5.web.include-css-file:@MICRO/media/main.css
p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
create-widget
  class:container
  widgets
    container
      class:row air-top
      widgets
        div
          class:col-100
          widgets
            div
              class:bg air-inner shaded rounded
              widgets
                micro.widgets.grid
                  columns
                    Name
                    Email
                    Phone no
                  rows
                    item
                      Name:Thomas Hansen
                      Email:thomas@gaiasoul.com
                      Phone no:12345678
                    item
                      Name:John Doe
                      Email:john@doe.com
                      Phone no:99887766
                    item
                      Name:Johhny Two-Times
                      Email:johhny@two-times.com
                      Phone no:67676767
                    item
                      Name:Jane Doe
                      Email:jane@doe.com
                      Phone no:99118822
                    item
                      Name:Peter Fisher
                      Email:peter@fisher.com
                      Phone no:91919191

Second example, dynamically populating grid after creation.

p5.web.include-css-file:@MICRO/media/main.css
p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
create-widget
  class:container
  widgets
    container
      class:row air-top
      widgets
        div
          class:col-80
          widgets
            div
              class:bg air-inner shaded rounded
              widgets
                micro.widgets.grid:my-grid
                  columns
                    Name
                    Email
                    Phone no
        div
          class:col-20
          widgets
            button
              class:fill
              innerValue:Populate grid
              onclick
                micro.widgets.grid.databind:my-grid
                  item
                    Name:Thomas Hansen
                    Email:thomas@gaiasoul.com
                    Phone no:12345678
                  item
                    Name:John Doe
                    Email:john@doe.com
                    Phone no:99887766
                  item
                    Name:Johhny Two-Times
                    Email:johhny@two-times.com
                    Phone no:67676767
                  item
                    Name:Jane Doe
                    Email:jane@doe.com
                    Phone no:99118822
                  item
                    Name:Peter Fisher
                    Email:peter@fisher.com
                    Phone no:91919191

Third example, widgets inside of your cells.

p5.web.include-css-file:@MICRO/media/main.css
p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
create-widget
  class:container
  widgets
    container
      class:row air-top
      widgets
        div
          class:col-100
          widgets
            div
              class:bg air-inner shaded rounded
              widgets
                micro.widgets.grid:my-grid
                  columns
                    Name
                    Email
                    Phone no
                  rows
                    item
                      Name:Thomas Hansen
                      Email
                        widgets
                          a
                            href:"mailto:thomas@gaiasoul.com"
                            innerValue:thomas@gaiasoul.com
                      Phone no:12345678
                    item
                      Name:John Doe
                      Email
                        widgets
                          a
                            href:"mailto:john@doe.com"
                            innerValue:john@doe.com
                      Phone no:99887766

Fourth example, widgets inside of your column headers.

p5.web.include-css-file:@MICRO/media/main.css
p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
create-widget
  class:container
  widgets
    container
      class:row air-top
      widgets
        div
          class:col-100
          widgets
            div
              class:bg air-inner shaded rounded
              widgets
                micro.widgets.grid:my-grid
                  columns
                    Name
                    Email
                    Phone no
                      widgets
                        a
                          href:#
                          role:button
                          innerValue:Phone no
                          onclick
                            set-widget-property:x:/../*/_event?value
                              innerValue:I was clicked!
                  rows
                    item
                      Name:Thomas Hansen
                      Email:thomas@gaiasoul.com
                      Phone no:12345678
                    item
                      Name:John Doe
                      Email:john@doe.com
                      Phone no:99887766

Fifth example, changing your rows, and/or your actual table as a whole.

p5.web.include-css-file:@MICRO/media/main.css
p5.web.include-css-file:@MICRO/media/skins/sea-breeze.css
create-widget
  class:container
  widgets
    container
      class:row air-top
      widgets
        div
          class:col-100
          widgets
            div
              class:bg air-inner shaded rounded
              widgets
                micro.widgets.grid:my-grid
                  style:"background-color:rgba(128,128,255,.2);"
                  columns
                    Name
                    Email
                    Phone no
                  rows
                    item
                      .row
                        style:"background-color:rgba(128,255,128,.2);"
                      Name:Thomas Hansen
                      Email:thomas@gaiasoul.com
                      Phone no:12345678
                    item
                      .row
                        role:button
                        onclick
                          create-widgets
                            micro.widgets.modal
                              class:micro-modal
                              widgets
                                h3
                                  innerValue:The second row was clicked
                                p
                                  innerValue:This was a clickable row ...
                      Name:John Doe
                      Email:john@doe.com
                      Phone no:99887766

To test out the above examples, make sure you’re using the latest release of Phosphorus Five, Micro, and System42 – Which is the Aphrodite KISS version 3.2. Then create a lambda page in the CMS, and make sure you set its “template” to “empty” in its settings.

To explain what’s going on, the grid in Micro simply creates an HTML table, and really nothing more – Allowing you to populate its content, in regards to both its attributes, rows, headers and cells in general – By adding whatever widgets/properties/attributes you wish to add inside of these elements.

In fact, by applying the above principle, I don’t think there exists a single “datagrid” on this planet, you couldn’t easily create yourself, and by creating your datagrid as an extension widget, making it reusable, you would end up with extremely “DRY” code.

Hence, the [micro.widgets.grid] instead of being a datagrid, becomes a 100% generic “datagrid framework”, allowing you to easily create your datagrids exactly as you see fit!