22 Dec, 2009, David Haley wrote in the 21st comment:
Votes: 0
Tyche said:
Barm said:
If we start passing a timeout to Select(), it will block for the duration of that timeout.


Does it? If so, this is Python specific as the operating system version of select() does not do that.
select() with a timeout returns either when the timeout expires OR when there is data ready.

Python's select behaves in the standard way (sit around until the timeout expires or data is ready or a socket is writable etc.). See, e.g., the manual entry on select. (Caveat lector: version 2.5, dunno if 2.6 changed something but I very strongly doubt it).
22 Dec, 2009, Barm wrote in the 22nd comment:
Votes: 0
Tyche said:
Does it? If so, this is Python specific as the operating system version of select() does not do that.
select() with a timeout returns either when the timeout expires OR when there is data ready.


Python's is normal. I was referring to it blocking while waiting on data.
22 Dec, 2009, Barm wrote in the 23rd comment:
Votes: 0
David Haley said:
Blocking is only a problem if there is something to do. If there are pending AI computations, that means there is something to do. I guess I'm not seeing why the poll should be hammered just for the sake of it. This can be rather expensive if you're doing it enough times for enough connections.

You don't want to "nice" yourself back to the system because you're wasting time on polls: that reduces your overall priority, including when you're actually doing useful work.


I'm not advocating hammering it just for the sake of it. In fact, I said the exact same thing about being expensive with enough rate and enough users. I fear this is turning into a bike-shed debate (edit) no, you were right.

so let's run some tests:

As fast as possible;

chat_server.py with full throttle polling, 0 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 9588 3780 2324 R 99.8 0.4 0:06.72 python

chat_server.py with full throttle polling, 100 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 10000 4052 2348 R 100.0 0.4 1:43.04 python


~100 times a second

chat_server.py with time.sleep(.01) in the game loop, 0 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 9588 3816 2356 S 0.3 0.4 0:00.10 python

chat_server.py with time.sleep(.01) in the game loop, 100 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 10012 4080 2376 S 6.6 0.4 0:02.90 python

chat_server.py with a .01 second Select() timeout, 0 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 9588 3816 2360 S 0.3 0.4 0:00.07 python

chat_server.py with a .01 second Select() timeout, 100 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
20 0 10000 4036 2344 R 7.3 0.4 0:03.38 python


~ 10 times a second

chat_server.py with time.sleep(.1) in the game loop, 100 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                 
20 0 10140 4088 2380 S 0.7 0.4 0:00.56 python


chat_server.py with a .1 second Select() timeout, 100 users:
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                 
20 0 10000 4076 2380 S 0.7 0.4 0:00.67 python


No suprise that constant polling is CPU wasteful. Using a timeout with Select vs. sleeping seems dead even. To be honest, I was not keen on hardcoding blocking into the server since I wanted to give all free cycles to Miniboa users. However, since blocking with Select() provides a superior user experience at low input rates and frees CPU usage on par with sleep(), I'll add it as a server variable. Plus, it's touch self-scaling in that total blocking time goes down as the input rate increases.
22 Dec, 2009, Barm wrote in the 24th comment:
Votes: 0
Committed revision 32.

Added a timeout property to TelnetServer(). You can specify it at creation;

telnet_server = TelnetServer(port=7777, address='', timeout=.05)

or change it on the fly. Default is 5 milliseconds.
22 Dec, 2009, David Haley wrote in the 25th comment:
Votes: 0
Barm said:
To be honest, I was not keen on hardcoding blocking into the server since I wanted to give all free cycles to Miniboa users.

I fully agree that you don't want the framework making strong policy decisions; you should always do just what you need, and not more. In this case though because the timeout is optional, the user gets to decide if they're fine with a (temporary, until-input-event) block. But yes, I completely agree with the hesitation to put in hard blocks.
23 Dec, 2009, Confuto wrote in the 26th comment:
Votes: 0
Barm said:
so let's run some tests:

Thanks for those figures.

I'm unclear as to the difference (in practice) between sleeping and using a select() timeout. Is it that the latter sleeps until there's activity while the former sleeps regardless?
23 Dec, 2009, Stoli wrote in the 27th comment:
Votes: 0
It would be really nice if miniboa had built-in support for telnet character mode so neat stuff like this could be implemented:

http://dead-souls.net/ds-charmode-faq.ht...

It may be just as easy as adding client.char_ready (similar to client.cmd_ready) and client.get_character() (similar to client.get_command()) to the TelnetClient. Maybe not though, heh. I spent a bit looking for the telnet specifications for character mode, but didn't find much. Anyhoo, the main thing I'm trying to do with it is implement a wordstar-like editor for mudmails to get less of a MUD feel and more of a BBS feel. :)

EDIT:
Confuto said:
Barm said:
so let's run some tests:

Thanks for those figures.

I'm unclear as to the difference (in practice) between sleeping and using a select() timeout. Is it that the latter sleeps until there's activity while the former sleeps regardless?


You have it right. Select() will only wait the full timeout if there is no data received from clients while sleep() completely stops everything until it wakes up. I don't think that there's a HUGE difference between the two methods, in practice, though using a timeout in select() just "feels" more right to me. :)
23 Dec, 2009, Barm wrote in the 28th comment:
Votes: 0
Confuto said:
Barm said:
so let's run some tests:

I'm unclear as to the difference (in practice) between sleeping and using a select() timeout. Is it that the latter sleeps until there's activity while the former sleeps regardless?


Stoli summed it up well. I was not expecting the timeout to Select() to reduced CPU usage on par with Sleep() – so that combined with David's suggestion to make the timeout a user variable makes it a superior, easier option, especially for low input rates like your 10hz example. Even the default of .005 seconds reduces idle CPU usage on the hello_server.py example from 98% to .03.
23 Dec, 2009, Barm wrote in the 29th comment:
Votes: 0
Stoli said:
It would be really nice if miniboa had built-in support for telnet character mode so neat stuff like this could be implemented:

http://dead-souls.net/ds-charmode-faq.ht...


If I get some time this weekend I'll look into it. I'd imagine sending the character mode IACs should be easy and just mimic how password mode works now. It does shift the burden of input handling to the coder, but that's what you want anyway.
24 Dec, 2009, donky wrote in the 30th comment:
Votes: 0
I have my own MUD framework, but what I would like other people to write me loosely coupled libraries of supporting functionality :robot: :wink:. In that spirit, I've taken your 'telnet.py' file and made it into a library with only the telnet negotiation logic left (and edited it a bit).

I'm not 100% satisfied with the way it works with an encompassing framework, and it took me a lot longer to strip back than I would have liked, but it involved less reading of overly waffley RFCs, so thanks for that.

The idea of a repository for Python MUD code where standard decouplable functionality like this could be collected into libraries was one I was going to suggest. But other than this, I am not sure there is much else. Maybe an intermud-3 client. Maybe a simple BaseHTTPServer-based web server with comet support, and the required HTML, CSS and Javascript that it serves for a client front-end. Although these are somewhat more extensive and probably harder to cleanly decouple in shareable ways :thinking:.
29 Dec, 2009, Barm wrote in the 31st comment:
Votes: 0
This is the Telnet RFC for line mode: http://www.faqs.org/rfcs/rfc1116.html

My first guess was wrong. You don't 'turn off' line-mode to get character mode. You send the client a request to begin negotiating with IAC DO LINEMODE who responds with IAC WILL LINEMODE. From there, it's sub-negotiation blocks to set/acknowledge the mode via some masks. Making a little progress on my checked out copy.

Stoli, do you think you'd use character mode 100% of the time or switch back and forth?
29 Dec, 2009, David Haley wrote in the 32nd comment:
Votes: 0
If the MUD did intelligent things with character mode like tab completion etc., I'd see little reason to use line mode. In fact, unless there's some kind of bandwidth issue where you don't want to send too many individual packets, I'm not sure why you'd use line mode in particular in the first place.
29 Dec, 2009, quixadhal wrote in the 33rd comment:
Votes: 0
I think the only reason to use line mode is if a given player wants to use a client that does its own editing/history/etc. However, if the mud implements proper terminal support (possibly even using termcap/curses), I doubt many would prefer a generic client's interface to one custom-designed and built into the actual mud itself.
30 Dec, 2009, Tyche wrote in the 34th comment:
Votes: 0
Barm said:
My first guess was wrong. You don't 'turn off' line-mode to get character mode. You send the client a request to begin negotiating with IAC DO LINEMODE who responds with IAC WILL LINEMODE. From there, it's sub-negotiation blocks to set/acknowledge the mode via some masks. Making a little progress on my checked out copy.


Maybe this will be more helpful than the RFC.
Stevens, TCP Illustrated said:
2. Character at a time.
…the way to enter this mode is for the server to have the SUPPRESS
GO AHEAD option enabled. This can be negotiated by having the client send a DO
SUPPRESS GO AHEAD (asking to enable the option at the server), or the server
sending a WILL SUPPRESS GO AHEAD to the client (asking to enable the option
itself). The server normally follows this with a WILL ECHO, asking to do the
echoing.

3. Line at a time.
This is often called "kludge line mode," because its implementation comes from
reading between the lines in RFC 858. This REG states that both the ECHO and
SUPPRESS GO AHEAD options must be in effect to have character-at-a-time input
with remote echo. Kludge line mode takes this to mean that when either of these
options is not enabled, Telnet is in a line-at-a-time mode.

4. Linemode.
We use this term to refer to the real linemode option, defined in RFC 1184 [Borman
1990]. This option is negotiated between the client and server and corrects all
the deficiencies in the kludge line mode. Newer implementations support this
option.


I'm not sure that real LINEMODE (4 above) is used by many clients. Most every mud client will default into using kludge linemode (3 above).
30 Dec, 2009, Zen_Clark wrote in the 35th comment:
Votes: 0
Tyche said:
I'm not sure that real LINEMODE (4 above) is used by many clients. Most every mud client will default into using kludge linemode (3 above).


What is the difference?
30 Dec, 2009, David Haley wrote in the 36th comment:
Votes: 0
The difference is that one is an implicit mode (based on a 'guess') whereas the other is an explicitly negotiated mode.
30 Dec, 2009, David Haley wrote in the 37th comment:
Votes: 0
I just noticed this…
Zen_Clark's signature said:
http://uncyclopedia.wikia.com/wiki/User:...
If you have time and the desire, please help make the above article the best joke it can be.

For starters your signature is pretty big (a few lines is ok but 14 is a bit excessive), but does it really have to contain things like this?
30 Dec, 2009, Tyche wrote in the 38th comment:
Votes: 0
Zen_Clark said:
Tyche said:
I'm not sure that real LINEMODE (4 above) is used by many clients. Most every mud client will default into using kludge linemode (3 above).

What is the difference?

See the link Barm posted in 31, and also http://www.faqs.org/rfcs/rfc1184.html

Edit: Rather RFC 1184 supersedes RFC 1131.
30 Dec, 2009, Barm wrote in the 39th comment:
Votes: 0
David Haley said:
I'm not sure why you'd use line mode in particular in the first place.


Well, line-mode makes for a clean demarcation point if you want to support completely different kinds of clients. For example, I've been toying with the idea of writing a Jabber server that would allow people to connect via instant messaging. Or maybe an ajax server for light web clients. These would be drop-in replacements for the client object I'm using now. That doesn't preclude providing a richer experience to Telnet users but it does make the code uncomfortably lopsided.

Secondly, I have a mental junk pile sitting behind me. It's things I was considering doing via Telnet that I scrapped after testing revealed that, collectively, MUD/Telnet clients really, really suck. Feature support is an awful, broken mess. Right down to little things like setting the background color. I just asked Tinyfuge to negotiate LINEMODE and got a WONT back. :sigh

I can see the usefulness of character mode though and I am interested in improving Miniboa. Right now I'm reading about how you can negotiate a table of values that special keys generate – which is pretty neat but, then again, I'm half afraid what testing with a dozen clients will reveal.
30 Dec, 2009, Barm wrote in the 40th comment:
Votes: 0
Tyche said:
Maybe this will be more helpful than the RFC.


Thanks Tyche, that is helpful.

Quote
I'm not sure that real LINEMODE (4 above) is used by many clients. Most every mud client will default into using kludge linemode (3 above).


That's been my observation so far.
20.0/53