On Sat, 05 Jan 2013 12:21:26 -0000, Nikita Popov <nikita....@gmail.com> wrote:

On Sat, Jan 5, 2013 at 3:07 PM, Nikita Nefedov <inefe...@gmail.com> wrote:
What symbols can give:
1. More convenient way to use it almost everywhere as a replacement for strings and sometimes for constants. There's a lot of code that uses arrays as a parameter-stores. For example, here's how you usually define a form in Symfony2:
        $builder
            ->add('title', 'text', array(
                'label' => 'Album title'
            ))
            ->add('title_alias', 'text', array(
                'label' => 'Album alias',
                'required' => false,
                'property_path' => 'properties.titleAlias'
            ))
            ->add('comment', 'text', array(
                'label' => 'Comment',
                'required' => false,
                'property_path' => 'properties.comment'
            ))
            ->add('labels', 'text', array(
                'label' => 'Musical labels',
                'required' => false,
                'property_path' => 'properties.labels'
            ))
            ->add('language', 'text', array(
                'required' => false,
                'property_path' => 'properties.language'
            ))
It could be improved this way:
        $builder
            ->add('title', :text, array(
                :label => 'Album title'
            ))
            ->add('title_alias', :text, array(
                :label => 'Album alias',
                :required => false,
                :property_path => 'properties.titleAlias'
            ))
            ->add('comment', :text, array(
                :label => 'Comment',
                :required => false,
                :property_path => 'properties.comment'
            ))
            ->add('labels', :text, array(
                :label => 'Musical labels',
                :required => false,
                :property_path => 'properties.labels'
            ))
            ->add('language', :text, array(
                :required => false,
                :property_path => 'properties.language'
            ))
2. Memory usage reduction. AFAIK, there's a lot of cases like the above and the use of symbols would affect on memory usage significantly.
3. Memory leaks. Symbols can't be just garbage collected as, for example zvals, it's not possible. But we can do it for every request, so I don't think it would be problem.
4. Autocompletion from IDEs.

Hi Nikita!

I don't quite understand what those symbols would actually be good for. If it's just for saving exactly one character for array keys (:foo vs "foo"), then this isn't worth it. If this is about memory savings, then I don't think it will help at all. PHP uses interned strings, so all those "label" etc strings in your above example actually use the same string value. The hash for those strings is also precomputed, so symbol don't have a performance advantage either. Regarding your fourth point, autocompletion is available for string array keys at least in PhpStorm and I guess also in other IDEs.

So, I don't yet really get what the point behind the symbols is.

Thanks,
Nikita

Hi, yes, you are right about interned strings, I didn't know it.
Actually my personal opinion is that strings should be used to store data (as values), not to retrieve it (not as keys). But strings are more developer-friendly than anything else (because you don't need to define new constant or new enumerable member for adding new parameter on receiving side, and you always see what this parameter is about). So you can see Symbols as enumerable that don't need to be initialized. There's actually no technical reason behind that.

Though there would be a little speed-up because with Symbols array's Buckets will keep numeric key, so instead of memcmp you will need to just compare two longs when retrieving element.
Actually this is looks a little bad now, AFAIK this is what happens when you trying to receive value from array by string key:
  1. Calling zend_new_interned_string_int for interning or getting already interned same string, receiving pointer to the stored string from it:
    1. Hash the string (O(n))
    2. Retrieve bucket from arBuckets
    3. Find needed bucket by iterating over all retrieved buckets (over *pLast) and comparing its keys with memcmp
    4. If found - return pointer to string, else create new bucket...
  2. Now that we have an interned string, we can try to retrieve value from array with string:
    1. Hash the string again (O(n))
    2. Retrieve bucket by hash fro arBuckets
    3. And again memcmp used for comparing strings

This could be improved with Symbols, so that you won't need hash string twice and use memcmp.

BTW do we really need a doubly linked list for interned strings (pListLast, pListNext) and all the extra members from HashTable/Bucket that needed for arrays? I know this is offtopic and these structs are used everywhere in PHP (because of DRY), but there are some places like this or class tables where we don't need arrays (PHP's arrays) functionality.

Reply via email to