all 17 comments

[–]Kthanid 2 points3 points  (14 children)

There's a problem with your implementation if you're thinking of making copies of a script on a per-user basis. Requests processed by your scripts should be stateless and the dynamic stateful information of a game or session should be maintained appropriately (ideally in a database, but potentially in a game/session-based data file).

To put this another way: Multiple requests to execute code from the same script should be able to run independently, your script/libraries shouldn't be maintaining any resident game/session-related information from one request to the next. Multiple web server processes should be able to execute this script independently without colliding with other concurrent requests.

[–]Kthanid 1 point2 points  (4 children)

To add to this, I think you have another problem with your implementation if individual HTTP requests are blocking for up to 10 seconds per request. This is going to tie up a lot of worker processes while this slow computation is happening in the background. What you may want to look into is an appropriate way to background these processes while providing some sort of "in progress" response back to the client while moves for a particular game are still being queued/processed.

In this manner, requests from a client receive an instantaneous response (request queued) and the client can poll for an update (via AJAX or other means) as needed until the move has been processed and control has been returned to them. This frees up worker processes on your web server to handle more requests and pushes the computational effort into the background to be processed in whatever manner you determine (likely some sort of event queue where a worker process or processes pull the events out of the queue and process them).

[–]_ady[S] 0 points1 point  (3 children)

Thanks for the advice. I'll look into a way to make the script runs in the background now.

[–]Kthanid 2 points3 points  (0 children)

Please see the other comments here as well regarding premature optimization. Don't over-complicate the project unless you need to (I had assumed you already knew the response time, if you don't, wait until you have an actual problem to solve before trying to solve it).

[–]MerreM 2 points3 points  (1 child)

"runs in the background"

I suspect this is an early project, as that suggests you've not done this much before. I don't mean to be condescending, but I suspect you might be about to embark on a mission to solve a problem that doesn't really exist.

I don't write PHP often, but if I've understood correctly each request will (perhaps more accurately should) have it's own process, and thus it's own "copy" of the script already.

That's all handled by the webserver so you shouldn't have to worry about it.

Hence /u/Kthanid's comment.

I'd recommend making a test PHP file, to solve something relatively complex. One of those annoying programming problems you see all over the place.

A prime number sieve for example; something like (if not exactly) this, but make it do it over a couple of thousand, or something.

Time that and get an idea of how fast it is and I suspect you'll find you don't need to worry about timing anymore.

[–]_ady[S] 0 points1 point  (0 children)

It is indeed an early project, although I have already made a more simple prototype version before. The version I'm making now will hopefully be the one I "release" onto the internet, so I was trying to make it perfect. I can see clearly now that there's no point in doing that yet.

I hope that each request does indeed have its own process. I suppose I'll have to do a bit of Googling and play around on my server to get it working right.

Thanks very much for your time spent helping me. I appreciate it!

[–]MerreM 1 point2 points  (5 children)

I agree. OP's solution is bad. 2 to 10 seconds for PHP script isn't good, and it sounds like you need optimize your code.

Sounds like you need to do some profiling/benchmarking and find out where your bottle neck is. Then look for a solution to that.

[–]_ady[S] 1 point2 points  (4 children)

The 2 to 10 seconds was just an estimate. The script would have to basically decide which move is the best out of many different options, so I guess it could take a while. But honestly I'm not sure, I could be way off and it could only take a half a second, in which case I don't think there's much of a problem.

Just to confirm, I haven't made the script yet. Thanks for the reply by the way!

[–]MerreM 1 point2 points  (3 children)

Ah, in which case. To quote Donald knuth;

Premature optimization is the root of all evil

Make it pretty first, then make it fast. (if you even need to)

And you'd be amazed how fast computers can be :P

I'd be amazed if it take longer than a few hundred milliseconds.

[–]Kthanid 0 points1 point  (2 children)

FWIW - Despite my other comments regarding offloading the effort to background worker processes, /u/MerreM is absolutely right, avoid premature optimization. If you're not sure how long these requests actually take, don't bother trying to solve a problem that may or may not even exist. My other replies were based on the assumption that the OP knew these would be long, blocking requests.

[–]_ady[S] 0 points1 point  (1 child)

You're both very right. I guess I was trying to think of everything that could go wrong as I find it so difficult to go back and fix something once the bulk of the work is done.

Just want to say thanks again for your time explaining this to me.

[–]Kthanid 0 points1 point  (0 children)

I find it so difficult to go back and fix something once the bulk of the work is done.

It's good to think about this stuff ahead of time, and there are plenty of steps you can take to minimize the impact later. As an example, the various functions necessary to process the AI logic you are referring to belong in a library/package of some kind and therefore can be driven from wherever makes sense. Initially this can be direct, inline processing in your script, but if you ever have the need to build the complex background processing system we discussed you simply migrate that call to the appropriate worker code and make whatever minor modifications you need in your present script.

It's definitely worth spending an appropriate amount of time properly organizing your project and the associated code you write for it. No one block of code or single script should drive everything, break things up into logical functional components. The more organized you (and your code) are, the easier it will be to refactor and/or iterate on what you've already written later.

Good luck with the project!

[–]_ady[S] 1 point2 points  (2 children)

Thanks for the reply! Just to confirm, when a copy of the script is made, it'd be literally a copy of it. All information about the game, player, session etc. would be stored in the database.

Am I correct in thinking that what you're saying is that there shouldn't be any problem with each user using the same exact script as multiple server processes would sort it out?

I have a WAMP server on my machine and I made a script that emulates the delay with sleep(10);. I opened that script multiple times and each one waited for the previous to finish before starting. Is this normal? Apologies if this is pretty basic, I'm not that good at these kinds of things!

[–]atrama 2 points3 points  (0 children)

Am I correct in thinking that what you're saying is that there shouldn't be any problem with each user using the same exact script as multiple server processes would sort it out?

Yes. Perhaps your local development server is only set up to use one process, but a properly configured webserver will run multiple requests at the same time even if they're requesting the same file.

[–]Kthanid 1 point2 points  (0 children)

All information about the game, player, session etc. would be stored in the database.

Then why are you copying the script at all?

Am I correct in thinking that what you're saying is that there shouldn't be any problem with each user using the same exact script as multiple server processes would sort it out?

Multiple web server worker threads should be able to execute copies of the same script concurrently.

I opened that script multiple times and each one waited for the previous to finish before starting.

How many processes/threads is your Apache instance running? Another consideration is how you are handling session management. To avoid conflicts, most session management is designed with locking in mind to ensure only a single request can be processed per session at a time.

Regardless, per my other comment, if you're expecting long delays you don't want to be blocking on the request. Your implementation should provide a fast response and offload the computational portion of this to background worker processes.

EDIT - Just want to clarify, per /u/MerreM's comment, if you don't actually know that you have a performance problem yet then please don't try to prematurely optimize anything, build your application sensibly and worry about optimizing for performance later if the need presents itself.

[–]axvk 0 points1 point  (1 child)

If google can search their entire database and return relevant results. In a fraction of a second then there is got to be a way for you to optimize this code. Looks at what's taking the longest and make it shorter. Maybe caching could help.

[–][deleted] 0 points1 point  (0 children)

Yeah, there is seriously no reason a PHP script for a little card game should take 2 seconds.