marc-mabe / php-enum

Simple and fast implementation of enumerations with native PHP
BSD 3-Clause "New" or "Revised" License
464 stars 36 forks source link

Immutable EnumSet #109

Closed marc-mabe closed 5 years ago

marc-mabe commented 5 years ago

Based on #108

PS 1: I still want to make some benchmarks for comparison PS 2: This make sense only if we make EnumMap immutable too

@prolic ping

marc-mabe commented 5 years ago

I'm not entirely sure about this. It would make sense only if both classes implement the same Interface. This means the interface would not make sure to handle immutable and mutable objects - in with DateTime and DateTimeImmutable.

Let's fist see what are the performance differences

marc-mabe commented 5 years ago

Here is the full benchmark: master -> 4.x -> 4.x (+ IteratorAggregate) -> 4.x (+IteratorAggregate + Immutable EnumSet)

+----------------+------------------------------+-----------------+--------------+--------------------------------+------------------------------------------+
| benchmark      | subject                      | tag:master:mean | tag:4.x:mean | tag:4.x_IteratorAggregate:mean | tag:4.x_IteratorAggregate_immutable:mean |
+----------------+------------------------------+-----------------+--------------+--------------------------------+------------------------------------------+
| EnumSet66Bench | benchAttachEnumeratorOnEmpty | 29.287μs        | 31.747μs     | 31.912μs                       | 41.938μs                                 |
| EnumSet66Bench | benchAttachValueOnEmpty      | 58.118μs        | 58.716μs     | 58.838μs                       | 74.214μs                                 |
| EnumSet66Bench | benchAttachEnumeratorOnFull  | 29.245μs        | 31.112μs     | 31.922μs                       | 41.867μs                                 |
| EnumSet66Bench | benchAttachValueOnFull       | 58.395μs        | 58.506μs     | 59.010μs                       | 73.980μs                                 |
| EnumSet66Bench | benchDetachEnumeratorOnEmpty | 30.443μs        | 30.084μs     | 30.228μs                       | 42.689μs                                 |
| EnumSet66Bench | benchDetachValueOnEmpty      | 59.323μs        | 59.440μs     | 59.819μs                       | 76.255μs                                 |
| EnumSet66Bench | benchDetachEnumeratorOnFull  | 30.418μs        | 30.235μs     | 30.526μs                       | 42.723μs                                 |
| EnumSet66Bench | benchDetachValueOnFull       | 59.539μs        | 59.155μs     | 59.367μs                       | 76.757μs                                 |
| EnumSet66Bench | benchContainsEnumeratorTrue  | 26.574μs        | 31.840μs     | 32.317μs                       | 31.927μs                                 |
| EnumSet66Bench | benchContainsValueTrue       | 55.635μs        | 58.691μs     | 58.582μs                       | 58.467μs                                 |
| EnumSet66Bench | benchContainsEnumeratorFalse | 26.448μs        | 31.883μs     | 31.790μs                       | 31.744μs                                 |
| EnumSet66Bench | benchContainsValueFalse      | 55.874μs        | 58.790μs     | 58.554μs                       | 58.662μs                                 |
| EnumSet66Bench | benchIterateFull             | 82.415μs        | 87.251μs     | 108.648μs                      | 108.792μs                                |
| EnumSet66Bench | benchIterateEmpty            | 0.554μs         | 0.574μs      | 19.426μs                       | 19.201μs                                 |
| EnumSet66Bench | benchCountFull               | 1.445μs         | 1.493μs      | 1.495μs                        | 1.504μs                                  |
| EnumSet66Bench | benchCountEmpty              | 0.366μs         | 0.397μs      | 0.397μs                        | 0.393μs                                  |
| EnumSet66Bench | benchIsEqual                 | 0.127μs         | 0.132μs      | 0.132μs                        | 0.132μs                                  |
| EnumSet66Bench | benchIsSubset                | 0.127μs         | 0.132μs      | 0.132μs                        | 0.132μs                                  |
| EnumSet66Bench | benchIsSuperset              | 0.167μs         | 0.178μs      | 0.177μs                        | 0.179μs                                  |
| EnumSet66Bench | benchUnion                   | 0.265μs         | 0.277μs      | 0.266μs                        | 0.267μs                                  |
| EnumSet66Bench | benchIntersect               | 0.261μs         | 0.274μs      | 0.263μs                        | 0.262μs                                  |
| EnumSet66Bench | benchDiff                    | 0.291μs         | 0.300μs      | 0.288μs                        | 0.292μs                                  |
| EnumSet66Bench | benchSymDiff                 | 0.263μs         | 0.272μs      | 0.262μs                        | 0.263μs                                  |
| EnumSet66Bench | benchGetOrdinalsFull         | 3.474μs         | 3.544μs      | 3.573μs                        | 3.529μs                                  |
| EnumSet66Bench | benchGetOrdinalsEmpty        | 0.377μs         | 0.405μs      | 0.402μs                        | 0.402μs                                  |
| EnumSet66Bench | benchGetValues               | 33.699μs        | 34.179μs     | 34.183μs                       | 34.057μs                                 |
| EnumSet66Bench | benchGetNames                | 37.440μs        | 38.139μs     | 38.276μs                       | 38.297μs                                 |
| EnumSet66Bench | benchGetEnumerators          | 31.761μs        | 32.128μs     | 32.283μs                       | 32.001μs                                 |
| EnumBench      | benchGetName                 | 6.588μs         | 5.782μs      |                                |                                          |
| EnumBench      | benchGetValue                | 2.656μs         | 2.666μs      |                                |                                          |
| EnumBench      | benchGetOrdinal              | 3.392μs         | 3.845μs      |                                |                                          |
| EnumBench      | benchIsByEnumerator          | 3.646μs         | 4.017μs      |                                |                                          |
| EnumBench      | benchIsByValue               | 6.419μs         | 6.724μs      |                                |                                          |
| EnumBench      | benchDetectConstants         | 86.766μs        | 85.821μs     |                                |                                          |
| EnumBench      | benchGetValues               | 0.380μs         | 0.399μs      |                                |                                          |
| EnumBench      | benchGetNames                | 0.125μs         | 0.131μs      |                                |                                          |
| EnumBench      | benchGetOrdinals             | 0.395μs         | 0.413μs      |                                |                                          |
| EnumBench      | benchGetEnumerators          | 11.989μs        | 11.760μs     |                                |                                          |
| EnumBench      | benchByValue                 | 28.830μs        | 29.518μs     |                                |                                          |
| EnumBench      | benchByValueAndInitialize    | 5,806.739μs     | 5,737.836μs  |                                |                                          |
| EnumBench      | benchByValueAndInstantiate   | 45.060μs        | 47.239μs     |                                |                                          |
| EnumBench      | benchByName                  | 9.749μs         | 10.237μs     |                                |                                          |
| EnumBench      | benchByNameAndInitialize     | 73.459μs        | 73.974μs     |                                |                                          |
| EnumBench      | benchByNameAndInstantiate    | 45.595μs        | 47.311μs     |                                |                                          |
| EnumBench      | benchByOrdinal               | 20.823μs        | 21.465μs     |                                |                                          |
| EnumBench      | benchByOrdinalAndInitialize  | 5,823.510μs     | 5,730.373μs  |                                |                                          |
| EnumBench      | benchByOrdinalAndInstantiate | 32.234μs        | 35.153μs     |                                |                                          |
| EnumBench      | benchGetByValues             | 31.191μs        | 32.522μs     |                                |                                          |
| EnumBench      | benchGetByEnumerator         | 4.712μs         | 5.468μs      |                                |                                          |
| EnumBench      | benchGetByCallStatic         | 18.200μs        | 20.783μs     |                                |                                          |
| EnumBench      | benchHasByEnumerator         | 4.599μs         | 5.191μs      |                                |                                          |
| EnumBench      | benchHasByValue              | 21.604μs        | 26.806μs     |                                |                                          |
| EnumSet32Bench | benchAttachEnumerator        | 10.562μs        | 11.244μs     | 11.198μs                       | 14.889μs                                 |
| EnumSet32Bench | benchAttachValue             | 21.685μs        | 22.114μs     | 22.232μs                       | 27.641μs                                 |
| EnumSet32Bench | benchDetachEnumerator        | 10.788μs        | 11.335μs     | 11.529μs                       | 14.994μs                                 |
| EnumSet32Bench | benchDetachValue             | 21.999μs        | 22.602μs     | 22.463μs                       | 28.013μs                                 |
| EnumSet32Bench | benchContainsEnumeratorTrue  | 10.575μs        | 11.804μs     | 11.756μs                       | 11.773μs                                 |
| EnumSet32Bench | benchContainsEnumeratorFalse | 10.544μs        | 11.802μs     | 11.773μs                       | 11.782μs                                 |
| EnumSet32Bench | benchContainsValueTrue       | 21.563μs        | 23.346μs     | 23.199μs                       | 23.186μs                                 |
| EnumSet32Bench | benchContainsValueFalse      | 21.615μs        | 23.257μs     | 23.307μs                       | 23.158μs                                 |
| EnumSet32Bench | benchIterateFull             | 33.523μs        | 35.523μs     | 46.422μs                       | 46.495μs                                 |
| EnumSet32Bench | benchIterateEmpty            | 0.401μs         | 0.416μs      | 7.837μs                        | 7.834μs                                  |
| EnumSet32Bench | benchCountFull               | 0.663μs         | 0.717μs      | 0.717μs                        | 0.720μs                                  |
| EnumSet32Bench | benchCountEmpty              | 0.193μs         | 0.207μs      | 0.208μs                        | 0.208μs                                  |
| EnumSet32Bench | benchIsEqual                 | 0.159μs         | 0.165μs      | 0.164μs                        | 0.164μs                                  |
| EnumSet32Bench | benchIsSubset                | 0.159μs         | 0.165μs      | 0.164μs                        | 0.164μs                                  |
| EnumSet32Bench | benchIsSuperset              | 0.144μs         | 0.159μs      | 0.159μs                        | 0.160μs                                  |
| EnumSet32Bench | benchUnion                   | 0.260μs         | 0.263μs      | 0.253μs                        | 0.253μs                                  |
| EnumSet32Bench | benchIntersect               | 0.257μs         | 0.264μs      | 0.253μs                        | 0.257μs                                  |
| EnumSet32Bench | benchDiff                    | 0.256μs         | 0.264μs      | 0.255μs                        | 0.257μs                                  |
| EnumSet32Bench | benchSymDiff                 | 0.254μs         | 0.266μs      | 0.254μs                        | 0.254μs                                  |
| EnumSet32Bench | benchGetOrdinalsFull         | 1.181μs         | 1.240μs      | 1.228μs                        | 1.237μs                                  |
| EnumSet32Bench | benchGetOrdinalsEmpty        | 0.707μs         | 0.723μs      | 0.722μs                        | 0.719μs                                  |
| EnumSet32Bench | benchGetValues               | 15.968μs        | 16.170μs     | 16.176μs                       | 16.176μs                                 |
| EnumSet32Bench | benchGetNames                | 17.735μs        | 18.261μs     | 18.228μs                       | 18.257μs                                 |
| EnumSet32Bench | benchGetEnumerators          | 14.946μs        | 15.354μs     | 15.308μs                       | 15.315μs                                 |
| EnumMapBench   | benchGetKeysEmpty            | 0.395μs         | 0.400μs      |                                |                                          |
| EnumMapBench   | benchGetKeysFull             | 23.008μs        | 22.944μs     |                                |                                          |
| EnumMapBench   | benchGetValuesEmpty          | 0.081μs         | 0.088μs      |                                |                                          |
| EnumMapBench   | benchGetValuesFull           | 0.082μs         | 0.089μs      |                                |                                          |
| EnumMapBench   | benchSearchTypeJuggling      | 1.418μs         | 1.458μs      |                                |                                          |
| EnumMapBench   | benchSearchStrict            | 0.671μs         | 0.718μs      |                                |                                          |
| EnumMapBench   | benchOffsetSetEnumerator     | 21.533μs        | 24.604μs     |                                |                                          |
| EnumMapBench   | benchOffsetSetValue          | 47.017μs        | 49.960μs     |                                |                                          |
| EnumMapBench   | benchOffsetUnsetEnumerator   | 18.890μs        | 19.882μs     |                                |                                          |
| EnumMapBench   | benchOffsetUnsetValue        | 45.957μs        | 47.261μs     |                                |                                          |
| EnumMapBench   | benchOffsetExistsEnumerator  | 17.477μs        | 18.851μs     |                                |                                          |
| EnumMapBench   | benchOffsetExistsValue       | 44.923μs        | 47.916μs     |                                |                                          |
| EnumMapBench   | benchContainsEnumerator      | 19.162μs        | 22.397μs     |                                |                                          |
| EnumMapBench   | benchContainsValue           | 45.832μs        | 47.982μs     |                                |                                          |
| EnumMapBench   | benchIterateFull             | 56.906μs        | 58.628μs     |                                |                                          |
| EnumMapBench   | benchIterateEmpty            | 0.219μs         | 0.224μs      |                                |                                          |
| EnumMapBench   | benchCountFull               | 0.086μs         | 0.090μs      |                                |                                          |
| EnumMapBench   | benchCountEmpty              | 0.086μs         | 0.090μs      |                                |                                          |
+----------------+------------------------------+-----------------+--------------+--------------------------------+------------------------------------------+

For me it tells me I should check where all the performance degrations comes from.

marc-mabe commented 5 years ago

@prolic It's ready now :)

I decided to have both mutable and immutable interfaces but with consistent naming: