Download notebook (.ipynb)

Comparison of Charting Libraries Performance#

import pandas as pd

from lets_plot import *
LetsPlot.setup_html()

Preliminaries#

def get_json_data(file_path):
    from requests import get

    r = get(file_path, stream=True)
    if r.status_code == 200:
        return r.json()
    else:
        return {}

def get_data(file_path):
    colors = {
        'LightningChart': '#e41a1c',
        'Plotly.js': '#4daf4a',
        'Canvas.js': '#ff7f00',
        'eCharts': '#ffff33',
        'Lets-Plot groups': '#377eb8',
        'Lets-Plot layers': '#984ea3',
    }
    data = {
        'test': [],
        'lib': [],
        'channels_count': [],
        'channel_data_points_per_second': [],
        'time_domain_interval': [],
        'loadup_speed_ms': [],
        'fps_avg': [],
        'fps_median': [],
        'frame_time_avg': [],
        'frame_time_median': [],
        'color': [],
    }
    for test, test_data in get_json_data(file_path).items():
        for lib, test_lib_data in test_data.items():
            data['test'].append(test)
            data['lib'].append(lib)
            data['channels_count'].append(test_lib_data['config']['channelsCount'])
            data['channel_data_points_per_second'].append(test_lib_data['config']['channelDataPointsPerSecond'])
            data['time_domain_interval'].append(test_lib_data['config']['timeDomainInterval'])
            data['loadup_speed_ms'].append(test_lib_data['loadupSpeedMs'])
            data['fps_avg'].append(test_lib_data['fps']['avg'])
            data['fps_median'].append(test_lib_data['fps']['median'])
            data['frame_time_avg'].append(test_lib_data['frameTime']['avg'])
            data['frame_time_median'].append(test_lib_data['frameTime']['median'])
            data['color'].append(colors[lib])
    return pd.DataFrame.from_dict(data)
df = get_data("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/lib_comparison.json")
df['load'] = df['channels_count'] * df['time_domain_interval']
df.head(6)
test lib channels_count channel_data_points_per_second time_domain_interval loadup_speed_ms fps_avg fps_median frame_time_avg frame_time_median color load
0 A LightningChart 1 1000 1000 101.7 58.412474 58.259538 17.258501 16.90 #e41a1c 1000
1 A Plotly.js 1 1000 1000 92.7 40.252554 40.922497 30.025803 24.25 #4daf4a 1000
2 A Canvas.js 1 1000 1000 101.5 23.045579 23.116954 43.772100 43.10 #ff7f00 1000
3 A eCharts 1 1000 1000 48.0 59.155815 59.053692 16.941370 17.00 #ffff33 1000
4 A Lets-Plot groups 1 1000 1000 68.1 49.928318 51.291719 19.021224 18.00 #377eb8 1000
5 A Lets-Plot layers 1 1000 1000 104.9 57.002319 58.007307 17.057078 17.00 #984ea3 1000

Here “Lets-Plot groups” is a realization of the benchmark in which each data channel corresponds to a group in aesthetics. In “Lets-Plot layers” each data channel corresponds to a plot layer.

def comparison1(col):
    return ggplot(df) + \
        geom_line(aes('load', col, color='color'), size=2, \
                  tooltips=layer_tooltips().line('@lib').line('{0}|@{0}'.format(col))) + \
        scale_x_log10() + scale_color_identity() + \
        ggtitle('Comparison of {0} through load increasing'.format(col))

def comparison2(col):
    return ggplot(df) + \
        geom_bar(aes(as_discrete('lib', order_by=col, order=1), col, fill='color'), stat='identity', \
                 tooltips=layer_tooltips().line('@lib').line('{0}|@{0}'.format(col))) + \
        facet_grid(x='test') + \
        scale_fill_identity() + \
        coord_flip() + \
        ggtitle('Comparison of {0} through tests'.format(col)) + \
        theme_void()

Comparison Charts#

comparison1('loadup_speed_ms')
comparison1('fps_avg')
comparison1('frame_time_avg')
comparison2('loadup_speed_ms')
comparison2('fps_avg')
comparison2('frame_time_avg')