php-general Digest 1 Apr 2012 11:56:20 -0000 Issue 7755

Topics (messages 317396 through 317403):

Re: Watch out for automatic type casting
        317396 by: Maciek Sokolewicz

Websocket using php
        317397 by: Leandro Dardini
        317401 by: Matijn Woudt
        317403 by: Tim Streater

Re: Thinking out loud - a continuation...
        317398 by: Jay Blanchard

Re: Node.PHP
        317399 by: Daniel Brown

Re: some good deals on good books
        317400 by: Daniel Brown

Re: Could apc_fetch return a pointer to data in shared memory ?
        317402 by: Stuart Dallas

Administrivia:

To subscribe to the digest, e-mail:
        php-general-digest-subscr...@lists.php.net

To unsubscribe from the digest, e-mail:
        php-general-digest-unsubscr...@lists.php.net

To post to the list, e-mail:
        php-gene...@lists.php.net


----------------------------------------------------------------------
--- Begin Message ---
On 30-03-2012 09:47, Arno Kuhl wrote:
-----Original Message-----
From: Simon Schick [mailto:simonsimc...@googlemail.com]
Sent: 29 March 2012 07:19 PM
To: a...@dotcontent.net
Cc: php-gene...@lists.php.net
Subject: Re: [PHP] Watch out for automatic type casting

Hi, Arno

FYI: I found a page in the php-manual that's exactly for that:
http://www.php.net/manual/en/language.operators.precedence.php

p.s. some of them were also new to me .... Thanks for getting me to read it.

Bye
Simon
----

Thanks Simon and others, thought it was typecasting, but precedence makes more 
sense.

I remember seeing that table when I first started using php, which is why I always use 
AND and OR rather than&&  and || because it's lower precedence than the 
assignment and the ternary operators, but I couldn't remember where I'd seen it. So 
thanks for linking to it.

Cheers
Arno
--

BTW interesting to note on that precedence page that "!" has a higher precedence than 
"=" (which you'd expect it to be) but you can still do
if (!$a = foo())

I use that form often (as I'm sure many others do) and just took it for granted 
that it works even though the order of precedence says it shouldn't.

It could be expanded to
if ($a = foo() != TRUE)
But that wouldn't get the expected result due to order of precedence, though at 
first glance you could reasonably expect it to work because of
if (!$a = foo())
being valid.

I think that's why it's so easy to be caught out (at least for me) by the 
similar form of
if ( $pos = strpos($sText, "test") !== FALSE)

Cheers
Arno

I would still suggest to explicitly supply the precedence you expect. Ie: if(($foo = $var) == true) { }
or if($a + (15*$b) ) { }

I know you can write it with fewer parentheses, but this at least makes it 100% clear you at all times WHAT is supposed to happen and you're 100% sure that PHP will understand what you WANT it to do aswell instead of having to guess, and fail at it because you don't know how guessing is implemented in the Zend Engine.
--- End Message ---
--- Begin Message ---
Hello,
I have the need to use websockets for the server part of an application I
am developing and I found with a big surprise no websocket class or
procedure is available on the net. Have I missed looking in some place?

Being really interested in using this protocol with PHP, I start from the
closest working thing: http://code.google.com/p/phpwebsocket/ and start
adapting it to the lastest RFC describing the protocol
http://tools.ietf.org/html/rfc6455, but it is really heavy to code and I
feel like "reinventing the wheel".

Is there anyone out there who has already written a websocket server in PHP
and like to share the code?

Leandro

--- End Message ---
--- Begin Message ---
On Sat, Mar 31, 2012 at 5:14 PM, Leandro Dardini <ldard...@gmail.com> wrote:
> Hello,
> I have the need to use websockets for the server part of an application I
> am developing and I found with a big surprise no websocket class or
> procedure is available on the net. Have I missed looking in some place?
>
> Being really interested in using this protocol with PHP, I start from the
> closest working thing: http://code.google.com/p/phpwebsocket/ and start
> adapting it to the lastest RFC describing the protocol
> http://tools.ietf.org/html/rfc6455, but it is really heavy to code and I
> feel like "reinventing the wheel".
>
> Is there anyone out there who has already written a websocket server in PHP
> and like to share the code?
>
> Leandro

Have you tried http://code.google.com/p/phpws/ ?

It seems to work pretty simple..

- Matijn

--- End Message ---
--- Begin Message ---
On 31 Mar 2012 at 16:14, Leandro Dardini <ldard...@gmail.com> wrote: 

> Hello,
> I have the need to use websockets for the server part of an application I
> am developing and I found with a big surprise no websocket class or
> procedure is available on the net. Have I missed looking in some place?
>
> Being really interested in using this protocol with PHP, I start from the
> closest working thing: http://code.google.com/p/phpwebsocket/ and start
> adapting it to the lastest RFC describing the protocol
> http://tools.ietf.org/html/rfc6455, but it is really heavy to code and I
> feel like "reinventing the wheel".
>
> Is there anyone out there who has already written a websocket server in PHP
> and like to share the code?

https://github.com/jam1401/PHP-Websockets-Server

--
Cheers  --  Tim

--- End Message ---
--- Begin Message ---
[snip]
On 3/30/2012 1:14 PM, Robert Cummings wrote:
On 12-03-27 11:11 AM, Jay Blanchard wrote:
[snip]On 3/27/2012 12:21 AM, Robert Cummings wrote:
>> [-- SNIP --]
Essentially, entries at the root and entries for the children are just
auto indexed array items but the actual entries in those arrays retain
the associative index structure for retrieval of the specific
information. let me know and I can probably whip you up something.

Robert that looks correct. Here is an example of the JSON that the guy
provided for me -

   var json = {
          id: "node02",
          name: "0.2",
          data: {},
          children: [{
              id: "node13",
              name: "1.3",
              data: {},
              children: [{
                  id: "node24",
                  name: "2.4",
                  data: {},
                  children: [{
                      id: "node35",
                      name: "3.5",
                      data: {},
                      children: [{
                          id: "node46",
                          name: "4.6",
                          data: {},
                          children: []
                      }]
                  }, {
                      id: "node37",
                      name: "3.7",
                      data: {},
                      children: [{
                          id: "node48",
                          name: "4.8",
                          data: {},
                          children: []
                      }, {
                          id: "node49",
                          name: "4.9",
                          data: {},
                          children: []
                      }, {
                          id: "node410",
                          name: "4.10",
                          data: {},
                          children: []
                      }, {
                          id: "node411",
                          name: "4.11",
                          data: {},
                          children: []
                      }]
                  },
Of course he properly closes up the JSON. I inserted id's (just an
auto-incrementing number) and the data portion where needed. The name:
is the part that has been the result of what you did before.

Here's the code... I did a bit of shuffling and actually tested against a test db table:

<?mysql :)

DROP TABLE IF EXISTS tiers;
CREATE TABLE tiers
(
    company     INT                 NOT NULL,
    tier1       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier2       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier3       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier4       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier5       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier6       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier7       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier8       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier9       VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier10      VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier11      VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier12      VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier13      VARCHAR( 32 )       NOT NULL        DEFAULT '',
    tier14      VARCHAR( 32 )       NOT NULL        DEFAULT ''
);

INSERT INTO tiers (company, tier1, tier2, tier3) VALUES
(1, 'exec-001','sub-exec-011','sub-sub-exec-111'),
(1, 'exec-001','sub-exec-011','sub-sub-exec-112'),
(1, 'exec-001','sub-exec-012','sub-sub-exec-121'),
(1, 'exec-001','sub-exec-012','sub-sub-exec-122'),
(1, 'exec-002','sub-exec-021','sub-sub-exec-211'),
(1, 'exec-002','sub-exec-021','sub-sub-exec-212'),
(1, 'exec-002','sub-exec-022','sub-sub-exec-221'),
(1, 'exec-002','sub-exec-022','sub-sub-exec-222');

?>

And here's the code:

<?php

function getTiers( $company )
{
    //
    // Establish the root.
    //

$sDb = &ijinn_getServiceRef( 'dbManager' );
$db = &$sDb->getConnectionRef();

    $query =
        "SELECT DISTINCT "
       ."   * "
       ."FROM "
       ."   tiers "
       ."WHERE "
       ."   company = {$company} ";

    $root = array();
    if( $db->query( $query ) )
    {
        while( ($row = $db->fetchRow()) )
        {
            $focus = &$root;
            for( $i = 1; $i <= 14; $i++ )
            {
                $name = trim( $row['tier'.$i] );
                if( $name === '' )
                {
                    break;
                }

                if( !isset( $focus[$name] ) )
                {
                    $focus[$name] = array
                    (
                        'name' => $name,
                        'children' => array(),
                    );
                }

                $focus = &$focus[$name]['children'];
            }
        }
    }

    $wrapper = array
    (
        'children' => &$root
    );

    postProcessTiers( $wrapper );

    return $root;
}

function postProcessTiers( &$root )
{
    $root['children'] = array_values( $root['children'] );

    foreach( array_keys( $root['children'] ) as $index )
    {
        postProcessTiers( $root['children'][$index] );
    }
}

function getTiersJson( $company )
{
    $tiers = getTiers( $company );
    $json = JSON_encode( $tiers );
}

$tiersJson = getTiersJson( 1 );

?>

This will output JSON with the following structure:

<?js

[
    {
        "name":"exec-001",
        "children":[
            {
                "name":"sub-exec-011",
                "children":[
                    {
                        "name":"sub-sub-exec-111",
                        "children":[]
                    },
                    {
                        "name":"sub-sub-exec-112",
                        "children":[]
                    }
                ]
            },
            {
                "name":"sub-exec-012",
                "children":[
                    {
                        "name":"sub-sub-exec-121",
                        "children":[]
                    },
                    {
                        "name":"sub-sub-exec-122",
                        "children":[]
                    }
                ]
            }
        ]
    },
    {
        "name":"exec-002",
        "children":[
            {
                "name":"sub-exec-021",
                "children":[
                    {
                        "name":"sub-sub-exec-211",
                        "children":[]
                    },
                    {
                        "name":"sub-sub-exec-212",
                        "children":[]
                    }
                ]
            },
            {
                "name":"sub-exec-022",
                "children":[
                    {
                        "name":"sub-sub-exec-221",
                        "children":[]
                    },
                    {
                        "name":"sub-sub-exec-222",
                        "children":[]
                    }
                ]
            }
        ]
    }
]

?>

PHP is smart enough to detect an array that only has consecutive integer keys and create the appropriate JavaScript array object. So we don't have to do any special processing of the JSON after we've post processed the tier structure itself.
[/snip]
Thanks Robert - I'll give this a go later today.

--- End Message ---
--- Begin Message ---
On Fri, Mar 30, 2012 at 21:33, Michael Save
<savetheinter...@omegasdg.com> wrote:
> Because "normal" PHP is not asynchronous.
>
> Also, I kind of doubt you can outperform node.js with standard PHP.

    Your doubts are indeed well-grounded.  Using node.js (indeed,
V8-based apps in general) are compiled as native machine code, which
don't require the added overhead of a parser, such as PHP.  With that
said, compiling PHP (such as with HopHop) would give at least
comparable performance results.

    Still, all in all, I would never discourage someone doing a
'node.php' application.  While its performance may not be quite as
good speed-wise, that doesn't mean it can't become more robust, more
generally-applicable, or even just find niche uses.  I've written
numerous socket servers in PHP for a variety of clients and uses,
where they made sense (speed of deployment, ease of code-management by
a number of developers who don't know C, et cetera).  I can easily see
where this could add value.

-- 
</Daniel P. Brown>
Network Infrastructure Manager
http://www.php.net/

--- End Message ---
--- Begin Message ---
On Sat, Mar 31, 2012 at 03:02, tamouse mailing lists
<tamouse.li...@gmail.com> wrote:
> I know there are quite a few people here who are just beginning to
> learn how to write programs as they also learn about PHP. O'Reilly has
> a deal on some pretty important books available electronically, save
> 50%. If this appeals to you, head to <
> http://shop.oreilly.com/category/deals/essential-code.do > and check
> them out.
>
> ( I apologize if this offends anyone's sensibilities. I am not in the
> employ of O'Reilly, nor is this going to make me any scratch. I just
> think this is a good chance to pick up some pretty useful books. )

    There was no affiliate code, so it doesn't appear as though there
was any ulterior motive.  As such, if anyone is offended, perhaps they
don't quite possess "sensibilities."  ;-P

    The link you provided will also benefit a lot who read the list
via numerous external sources, such as forums that auto-populate with
content from these lists, and the archives, which are slurped by
Google so quickly that, on occasion, I've seen posts show up in Google
before I even get the chance to read the original email.

    Great job on a thoughtful post.

-- 
</Daniel P. Brown>
Network Infrastructure Manager
http://www.php.net/

--- End Message ---
--- Begin Message ---
On 31 Mar 2012, at 13:14, Simon wrote:

> Thanks again Stuart.
> 
> On 31 March 2012 12:50, Stuart Dallas <stu...@3ft9.com> wrote:
>> On 31 March 2012 11:19, Simon <slg...@gmail.com> wrote:
>> Thanks for your answer.
>> 
>> On 31 March 2012 09:50, Stuart Dallas <stu...@3ft9.com> wrote:
>> On 31 Mar 2012, at 02:33, Simon wrote:
>> 
>> > Or: Why doesn't PHP have Applications variables like ASP.NET  (and node.js)
>> > ?
>> >
>> > Hi,
>> >
>> > I'm working on optimising a php application (Drupal).
>> >
>> > The best optimisation I've found so far is to use APC to store various bits
>> > of Drupal data in RAM.
>> >
>> > The problem with this is that with Drupal requiring say 50Mb of data* per
>> > request is that lots of cpu cycles are wasted de-serialising data out of
>> > apc_fetch. Also 50Mb of data per http process !! is wasted by each one
>> > re-creating it's own copy of the shared data.
>> 
>> 50MB? WTF is it storing?? I've never used Drupal, but based purely on that 
>> it sounds like an extremely inefficient piece of software that's best 
>> avoided!
>> 
>> All sorts of stuff (taxonomies, lists of data, menu structures, 
>> configuration settings, content etc). Drupal is a sophisticated application. 
>> Besides, 50Mb of data seems like relatively tiny "application state" to want 
>> to access in fastest possible way. It's not hard to imagine wanting to use 
>> *much* more than this in future
>>  
>> 
>> > If it were possible for apc_fetch (or similar function) to return a pointer
>> > to the data rather than a copy of the data this would enable incredible
>> > reduction in cpu and memory usage.
>> 
>> Vanilla PHP adheres to a principle known as "shared nothing architecture" in 
>> which, shockingly, nothing is shared between processes or requests. This is 
>> primarily for scalability reasons; if you stick to the shared nothing 
>> approach your application should be easily scalable.
>> 
>> Yes, I know. I think the effect of this is that php will scale better (on 
>> average) in situations where requests don't need to share much data such as 
>> "shared hosting". In an enterprise enviroment where the whole server might 
>> be dedicated to single application, "shared nothing" seems to be a synonym 
>> for "re-load everything" ?
>> 
>> Yes, on one level that is what it means, but alternatively it could mean 
>> being a lot more conservative about what you load for each request.
> 
> Um, I want to be *less* conservative. Possibly *much* less. (like Gigabyes or 
> even eventually Petabytes of shared data !)

We appear to have drifted off the point. There's a big difference between data 
that an application needs to access and "application variables".

What you're describing is a database. If you want something more performant 
there are ways to optimise access to that amount of data, but if not I've 
completely lost what the problem is that you're trying to solve.

>> > This is essentially how ASP.NET Application variables and node.js work.
>> 
>> Not a valid comparison. Node.js applications can only share variables within 
>> a single process, and they can do so because it's single-threaded. Once you 
>> scale your app beyond a single process you'd need to add a custom layer on 
>> to share data between them.
>> 
>> I'm not sure about the architecture behind IIS and ASP.net but I imagine 
>> there are similar paradigms at work.
>> 
>> I totally agree although,  I *think* IIS uses multiple threads running in a 
>> single process (or "Application Pool").
>> I realise that ASP.NET / node.js have their own architectural issues but I'm 
>> confident that for enterprise applications
>> (ie Drupal) the option for "shared something" is capable of many orders of 
>> magnitude higher performance and scalability than "shared nothing".
>> 
>> And that's why there are so many options around that enable such 
>> functionality. The need for something doesn't in any way imply that it 
>> should be part of the core system. Consider the impact such a requirement 
>> would have on the environment in which you run PHP. By delegating that 
>> "feature" to third-party modules, the PHP core doesn't need to concern 
>> itself with the details of how to share data between processes on every 
>> target platform.
> 
> Agreed. If you were able to point me in the direction of such a 3rd party 
> module I'd be a very happy man.

APC and memcached are two of the most common examples, other than the vast 
array of DBMSes out there.
 
>> > I'm surprised PHP doesn't already have Application variables, given that
>> > they are so similar to Session Variables and that it's been around for a
>> > long time in ASP / ASP.NET.
>> 
>> Just because x does it, doesn't mean y should. I've used lots of languages 
>> over the years, including classic ASP, ASP.net, Perl, Python, Ruby, PHP 
>> (obv), and more, and I'm yet to see a compelling reason to want application 
>> variables. 
>> 
>> The reason that I'm suggesting this is because taking the example of Drupal, 
>> the ability to share information between requests "by reference" rather than 
>> by copy has the potential to be *millions* of times faster. Assuming I had 
>> say a 5Mb dataset that I wanted to re-use between request and lets say 
>> (optimistically) that "de-serialising" an object from apc_fetch takes 10 cpu 
>> cycles per "character" it would be ~50 million* times faster to pass this 
>> data as a pointer ?  *Assuming simplistically that the pointer can be passed 
>> in 1 cpu cycle.
>> 
>> You say "by reference" but I'm not convinced that the implementation of  
>> application variables means they're not copied into each process. In 
>> addition, the cost of de-serialising data is minuscule in the grand scheme 
>> of any non-trivial application.
> 
> No, I am 100% certain they're not copied into each process.

One process cannot access data in another process without it being copied. A 
thread can access data from another thread without copying it, but if it's not 
read-only it needs to be access-controlled which would be a massive performance 
hit. I don't know because I've never cared, but I'd bet good money that when 
you read an application variable in asp.net, you get a copy of that data.

>> >Let go of the possibility of application variables and your thinking will 
>> >shift to other ways of solving the problem.
>> I've spent a long time thinking about this and whilst I can think of many 
>> other ways to "solve" this problem (APC, memcached, SHM) they all suffer 
>> from the problem that "passing by copy" is potentially millions or billions 
>> of times slower than passing by reference and is potentially *hundreds* of 
>> times less memory efficient.
>> 
>> If you had a further suggestions I'd be very interested to hear them.
>> 
>> See below.
>>  
>> > I just wondered if there was a reason for not having this functionality or
>> > if it's on a road map somewhere or I've missed something :) ?
>> 
>> 
>> As far as I am aware, ASP and ASP.net are the only web technologies to 
>> support application variables out of the box. You think that's simply 
>> because the others just haven't gotten around to it yet?
> 
> Honestly, I don't know. I realise there benefits in certain circumstances to 
> shared nothing. However if I have an application where I want to maintain 
> state between requests (ie any non trivial application?) it seems that 
> Application variables (or an event loop) are many orders of magnitude more 
> performant and
> there doesn't seem to be a way to achieve the same in PHP.

What do you want to store between requests? If it's per-user then you want 
sessions (I have some views on the "traditional" implementation and usage of 
sessions, but that's for another email). If you want to store data that needs 
to be made available to every user, that's why databases exist. If a database 
is too slow then you can use memcached. If you're only ever going to be on one 
server you can use APC. There's no need for PHP to natively support this 
feature.

>> It would be great if someone could tell me specifically why I'm wrong OR if 
>> I can persuade the php community that "shared nothing" is wrong in certain 
>> circumstances (basically enterprise applications!) and application variables 
>> could be added to PHP 
>> 
>> You're not wrong in saying that it can be incredibly useful to be able to 
>> share common data between processes, but I think you're approaching it from 
>> the wrong angle. Let's take the list of things that Drupal wants to store...
>> 
>> * taxonomies
>> * menu structures
>> * configuration settings
>> 
>> I'm guessing these things don't change while the application is running, and 
>> could easily be dumped out to PHP files that can then be included as needed, 
>> at a far lower processing cost than accessing a shared data store.
>> 
> I think this suffers from the at least the same overhead as apc_fetch
> 
> And an advantage of Applications variables is that they can change (very) 
> frequently.

Reading PHP files, especially when you use a bytecode cache, is one of the 
fastest way to read data. If the data is changing frequently then you want a 
database / memcached / APC (see my previous answer).

>> * content
>> 
>> If you're talking about caching static content please refer to my answer 
>> above - no reason these can't also be stored in files. If you're talking 
>> about caching generated output then memcached is the best solution I've 
>> found.
> 
> I've actually found caching to a filesystem to be 5x faster than memcached 
> (remembering that *nix automatically caches frequently used files in RAM)

Above you said that using files would have at least the same overhead as APC.

>> * lists of data
>> 
>> Not sure what you mean by this, but one of the above two answers probably 
>> applies.
> 
> Actually, I mean Drupal "Views" you are correct. 

For caching output I've used files (fast when subsequent requests bypass PHP), 
memcached (incredibly fast), and a caching proxy.

>> My basic point is that the shared nothing approach to scalability has been 
>> proven as a big benefit, and I would hate to see that feature of PHP 
>> compromised just because use cases exist where it's not idea. Better to have 
>> add-ons to provide what you need.
> 
> As above, agreed. If you were able to point me in the direction of an add-on 
> I'll be very happy.

I have, several times. APC is one option but is limited to a single server. 
Memcached is, IMO, the best multi-server option. If you're talking about more 
than ~1MB of data I'd go with a database.

Getting back to the gigabytes or even petabytes of data you want to share 
across the application, what do you have against databases?

-Stuart

-- 
Stuart Dallas
3ft9 Ltd
http://3ft9.com/

--- End Message ---

Reply via email to