jueves, 7 de noviembre de 2013

JSON vs YAML

The other day I was thinking of creating a config file for one of my projects because it's getting bigger  and controlling with IFs the values of some variables depending if the server is being executed in the production machine or my development laptop was supposed to be just a temporary patch that has been there too much time. So I searched on pub for a package that could load config files and I reached to dart_config.

When I was reading the documentation  I learned that it supported 2 different formats for loading the configuration, JSON and YAML, and I asked myself (and my friends) which will be a better option. I personally like more using curly braces like in JSON but YAML has somre pretty badass features too so I just decided to use the most efficient one. We thought the most efficient one would be JSON because it seems easier to parse but we weren't completely sure so one of my friends thought that making a little benchmark would be a good idea, so I did.

I created a simple yaml file, then I created a json file from it and after that I created another json file compressing the previous one (taking of all the whitespaces and line breaks). And I created the following code:

import 'dart:convert';
import 'dart:io';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:yaml/yaml.dart' as YAML;

void main() {
  YamlBenchmark.main();
  JsonBenchmark.main();
  CompressedJsonBenchmark.main();
}


class YamlBenchmark extends BenchmarkBase {
  const YamlBenchmark() : super("YAML");

  final String text = new File("./test.yaml").readAsStringSync();

  static void main() {
    new YamlBenchmark().report();
  }

  void run() {
    YAML.loadYaml(text);
  }
}

class JsonBenchmark extends BenchmarkBase {
  const JsonBenchmark() : super("JSON");

  final String text = new File("./test.json").readAsStringSync();

  static void main() {
    new JsonBenchmark().report();
  }

  void run() {
    JSON.decode(text);
  }
}

class CompressedJsonBenchmark extends BenchmarkBase {
  const CompressedJsonBenchmark() : super("Compressed JSON");

  final String text = new File("./compressedTest.json").readAsStringSync();

  static void main() {
    new CompressedJsonBenchmark().report();
  }

  void run() {
    JSON.decode(text);
  }
}


And the results of this benchmark had JSON as a clear winner:
YAML(RunTime): 5755.747126436781 us.
JSON(RunTime): 29.408737335862483 us.
Compressed JSON(RunTime): 24.88459767826704 us.

But then I realized that making the tests like this I made dissapear one of YAML's advantage against not compressed JSON, a smaller file that would take less time to read. So I decided to change the benchmark so the File is read each time and the time it takes to read it is part of the result.

import 'dart:convert';
import 'dart:io';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:yaml/yaml.dart' as YAML;

void main() {
  YamlBenchmark.main();
  JsonBenchmark.main();
  CompressedJsonBenchmark.main();
}

class YamlBenchmark extends BenchmarkBase {
  const YamlBenchmark() : super("YAML");

  static void main() {
    new YamlBenchmark().report();
  }

  void run() {
    String text = new File("./test.yaml").readAsStringSync();
    YAML.loadYaml(text);
  }
}

class JsonBenchmark extends BenchmarkBase {
  const JsonBenchmark() : super("JSON");

  static void main() {
    new JsonBenchmark().report();
  }

  void run() {
    String text = new File("./test.json").readAsStringSync();
    JSON.decode(text);
  }
}

class CompressedJsonBenchmark extends BenchmarkBase {
  const CompressedJsonBenchmark() : super("Compressed JSON");

  static void main() {
    new CompressedJsonBenchmark().report();
  }

  void run() {
    String text = new File("./compressedTest.json").readAsStringSync();
    JSON.decode(text);
  }
}

And here are the results with the modified code:
YAML(RunTime): 6766.891891891892 us.
JSON(RunTime): 240.87679152113694 us.
Compressed JSON(RunTime): 206.1218179944347 us.

The winner continues being JSON but what before was 198x faster is now just 28x faster, althought the absolute time has increased more with the YAML file than with the JSON. We can also see the compressed JSON being (obviously) less affected by having to read the file. Probably with very big files we would see a smaller difference between YAML and JSON and bigger between compressed and uncompressed but that is a test for another day, because my config files won't bee too big and with small files we have a clear winner: JSON.