PERF: optimize storage type for codes in Categoricals (GH8453)

closes #8453

So easy enough to optimize the dtype of the codes array depending on the number of categories. Most
of the time will simply be ``int8``. So pretty good savings.

This doesn't completely solve the storage issues as currently ``factorize`` returns a ``int64``, but can deal with that later (as might also need some more cython definitions).

And of course in the extreme case (where len(categories) == len(codes) you are better off with an object dtype).

```
In [1]: s = Series(['foo','bar']*1000)

In [2]: s.nbytes
Out[2]: 16000

In [3]: s.astype('category').nbytes
Out[3]: 2016

In [5]: s.astype('category').values.codes
Out[5]: array([1, 0, 1, ..., 0, 1, 0], dtype=int8)
```
Please dont call the arg "values", it's codes.

I haven't looked at the code, but please include a test for when the length
of a series get longer during appending than the current dtype can hold.
Am 03.10.2014 23:03 schrieb "Stephan Hoyer" <notifications@github.com>:

> In pandas/core/categorical.py:
>
> > @@ -1407,7 +1421,7 @@ def _get_codes_for_values(values, categories):
> >      (hash_klass, vec_klass), vals = _get_data_algo(values, _hashtables)
> >      t = hash_klass(len(categories))
> >      t.map_locations(com._values_from_object(categories))
> > -    return com._ensure_platform_int(t.lookup(values))
> > +    return _get_codes_dtype(t.lookup(values),categories)
>
> pep8 nit: add a space after the comma
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/pydata/pandas/pull/8455/files#r18419449>.
>