<commit_before># Overview

This project was created to compare the payload size and performance of serialization formats (Protocol Buffers, XML, JSON, YAML, TOML, native PHP object serialization).

# Setup

I used PHP package `athletic/athletic` to execute this benchmark, simply comparing the performance of encoding / decoding a simple data structure.

*NOTE:* I did not use the official Protobuf library for PHP as I could not reliably get the extension to work and the performance of the native PHP code package was far slower than any of the other technologies in this benchmark.

## Platform

* Mac OS X
* protoc 3.2.0
* PHP 7.1.1
* basho/protobuf
* symfony/yaml
* yosymfony/toml
* sabre/xml

## Proto message

```
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  message PhoneNumber {
    enum PhoneType {
      HOME = 0;
      MOBILE = 1;
      WORK = 2;
    }

    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
```

# Payload

Below, you can see the size and raw output of the serialized payload using each serialization method.

|Technology|PayloadSize|
|PB|712b|
|JSON|1104b|
|YAML|1104b|
|TOML|1664b|
|PHP|1864b|
|XML|2728b|

## PB

728 bits

```

Christopher <EMAIL>in<EMAIL>"

0123456789"

1234567890"

2345678901
```

## XML

2728 bits

```xml
<?xml version="1.0"?>
<person>
 <full_name><NAME></full_name>
 <id>1</id>
 <email><EMAIL></email>
 <phone>
  <type>home</type>
  <number>0123456789</number>
 </phone>
 <phone>
  <type>mobile</type>
  <number>1234567890</number>
 </phone>
 <phone>
  <type>work</type>
  <number>2345678901</number>
 </phone>
</person>
```

## JSON

1104 bits

```json
{"name":"<NAME>","id":1,"email":"<EMAIL>","phone":{"home":"0123456789","mobile":"1234567890","work":"2345678901"}}
```

## YAML

1104 bits

```yaml
name: '<NAME>'
id: 1
email: <EMAIL>
phone:
    home: '0123456789'
    mobile: '1234567890'
    work: '2345678901'
```

## TOML

1664 bits

```toml
name = "<NAME>"
id = 1
email = "<EMAIL>"

[[phone]]
type = "home"
number = "0123456789"

[[phone]]
type = "mobile"
number = "1234567890"

[[phone]]
type = "work"
number = "2345678901"
```

## PHP Object Serialization

1864 bits

```php
O:25:"ProtobufBenchmarks\Person":4:{s:4:"name";s:19:"<NAME>";s:2:"id";i:1;s:5:"email";s:18:"<EMAIL>";s:5:"phone";a:3:{s:4:"home";s:10:"0123456789";s:6:"mobile";s:10:"1234567890";s:4:"work";s:10:"2345678901";}}
```

# Performance

|Technology|Encode Ops/Second|Decode Ops/Second|
|PHP|239,935|173,060|
|JSON|95,911|198,406|
|PB|23,160|10,557|
|XML|1,014|597|
|YAML|685|339|
|TOML|678|82|

```
ProtobufBenchmarks\DecodeEvent
    Method Name      Iterations    Average Time      Ops/second
    --------------  ------------  --------------    -------------
    decodeProtobuf: [1,000     ] [0.0000947201252] [10,557.41848]
    decodeXml     : [1,000     ] [0.0016745967865] [597.15868]
    decodeJson    : [1,000     ] [0.0000050401688] [198,406.05487]
    decodeYaml    : [1,000     ] [0.0029436485767] [339.71446]
    decodeToml    : [1,000     ] [0.0120675928593] [82.86657]
    decodePhp     : [1,000     ] [0.0000057783127] [173,060.90114]


ProtobufBenchmarks\EncodeEvent
    Method Name      Iterations    Average Time      Ops/second
    --------------  ------------  --------------    -------------
    encodeProtobuf: [1,000     ] [0.0000431771278] [23,160.41039]
    encodeXml     : [1,000     ] [0.0009857304096] [1,014.47616]
    encodeJson    : [1,000     ] [0.0000104262829] [95,911.45869]
    encodeYaml    : [1,000     ] [0.0014583096504] [685.72542]
    encodeToml    : [1,000     ] [0.0014738268852] [678.50574]
    encodePhp     : [1,000     ] [0.0000041677952] [239,935.01516]
```<commit_msg>Fix tables and improve README.<commit_after># Overview

This project was created to compare the payload size and performance of serialization formats (Protocol Buffers, XML, JSON, YAML, TOML, native PHP object serialization).

# Setup

I used PHP package `athletic/athletic` to execute this benchmark, simply comparing the performance of encoding / decoding a simple data structure.

*NOTE:* I did not use the official Protobuf library for PHP as I could not reliably get the extension to work and the performance of the native PHP code package was far slower than any of the other technologies in this benchmark.

## Platform

* Mac OS X
* protoc 3.2.0
* PHP 7.1.1
* basho/protobuf
* symfony/yaml
* yosymfony/toml
* sabre/xml

## Dependency Setup

```bash
# install protoc
brew install protobuf

# install composer deps
composer install

# generate proto messages
./vendor/bin/protoc-gen-php --package='ProtobufBenchmarks\Message' --use-namespaces --psr --destination='src/' person.proto
```

## Execution

```bash
./vendor/bin/athletic -p src/ -b vendor/autoload.php
```

## Proto message

```
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  message PhoneNumber {
    enum PhoneType {
      HOME = 0;
      MOBILE = 1;
      WORK = 2;
    }

    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
```

# Payload

Below, you can see the size and raw output of the serialized payload using each serialization method.

| Technology | PayloadSize |
|------------|-------------|
| PB         | 712b        |
| JSON       | 1104b       |
| YAML       | 1104b       |
| TOML       | 1664b       |
| PHP        | 1864b       |
| XML        | 2728b       |

## PB

728 bits

```

<NAME>in<EMAIL> <EMAIL>"

0123456789"

1234567890"

2345678901
```

## XML

2728 bits

```xml
<?xml version="1.0"?>
<person>
 <full_name><NAME></full_name>
 <id>1</id>
 <email><EMAIL></email>
 <phone>
  <type>home</type>
  <number>0123456789</number>
 </phone>
 <phone>
  <type>mobile</type>
  <number>1234567890</number>
 </phone>
 <phone>
  <type>work</type>
  <number>2345678901</number>
 </phone>
</person>
```

## JSON

1104 bits

```json
{"name":"<NAME>","id":1,"email":"<EMAIL>","phone":{"home":"0123456789","mobile":"1234567890","work":"2345678901"}}
```

## YAML

1104 bits

```yaml
name: '<NAME>'
id: 1
email: <EMAIL>
phone:
    home: '0123456789'
    mobile: '1234567890'
    work: '2345678901'
```

## TOML

1664 bits

```toml
name = "<NAME>"
id = 1
email = "<EMAIL>"

[[phone]]
type = "home"
number = "0123456789"

[[phone]]
type = "mobile"
number = "1234567890"

[[phone]]
type = "work"
number = "2345678901"
```

## PHP Object Serialization

1864 bits

```php
O:25:"ProtobufBenchmarks\Person":4:{s:4:"name";s:19:"<NAME>";s:2:"id";i:1;s:5:"email";s:18:"<EMAIL>";s:5:"phone";a:3:{s:4:"home";s:10:"0123456789";s:6:"mobile";s:10:"1234567890";s:4:"work";s:10:"2345678901";}}
```

# Performance

| Technology | Encode Ops/Second | Decode Ops/Second |
| ---------- | ----------------- | ----------------- |
| PHP        | 239,935           | 173,060           |
| JSON       | 95,911            | 198,406           |
| PB         | 23,160            | 10,557            |
| XML        | 1,014             | 597               |
| YAML       | 685               | 339               |
| TOML       | 678               | 82                |

```
ProtobufBenchmarks\DecodeEvent
    Method Name      Iterations    Average Time      Ops/second
    --------------  ------------  --------------    -------------
    decodeProtobuf: [1,000     ] [0.0000947201252] [10,557.41848]
    decodeXml     : [1,000     ] [0.0016745967865] [597.15868]
    decodeJson    : [1,000     ] [0.0000050401688] [198,406.05487]
    decodeYaml    : [1,000     ] [0.0029436485767] [339.71446]
    decodeToml    : [1,000     ] [0.0120675928593] [82.86657]
    decodePhp     : [1,000     ] [0.0000057783127] [173,060.90114]


ProtobufBenchmarks\EncodeEvent
    Method Name      Iterations    Average Time      Ops/second
    --------------  ------------  --------------    -------------
    encodeProtobuf: [1,000     ] [0.0000431771278] [23,160.41039]
    encodeXml     : [1,000     ] [0.0009857304096] [1,014.47616]
    encodeJson    : [1,000     ] [0.0000104262829] [95,911.45869]
    encodeYaml    : [1,000     ] [0.0014583096504] [685.72542]
    encodeToml    : [1,000     ] [0.0014738268852] [678.50574]
    encodePhp     : [1,000     ] [0.0000041677952] [239,935.01516]
```
{'fraction_non_alphanumeric': 0.1827027027027027, 'fraction_numerical': 0.15591591591591591, 'mean_word_length': 2.7186243858865566, 'pattern_counts': {'":': 16, '<': 82, '<?xml version=': 2, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1904443', 'n_tokens_mistral': 3859, 'n_tokens_neox': 2989, 'n_words': 700}