Lear beat me to it, but this is how I design all of my scripts that require listens:
I always like to have my script doing nothing when idle, including removing unnecessary listens.
If I require a perpetual listen, I only use one listen and use the simplest method to verify if the messages are meant for my script--checking for a key, value or string within the received data before processing anything. By design, I try not to have perpetual listens, but sometimes it's unavoidable.
Listens that don't need to be perpetual have timeouts (dialog menus, for instance) after x seconds, thus removing the listen. This keeps listens to a minimum. The general rule is to keep the script idle until interacted with by an avatar.
If any listens need to be turned on/off repeatedly using the same channel, I use llListenControl.
I hardly ever use states. I find I can achieve the same result (i.e. a switch) with boolean integers and much less code.
Keep chat messages to a minimum by combining data into as few messages as possible. One message per interaction is what I always strive for.
Multiplicity. As was stated earlier, you have to conceptualize how your script will be used and how many will be used in a sim. One script may not cause much of a dip in sim performance, but if you multiply that by 10, 20, 50, 100 what would the performance be?
I always try to keep my functionality within one script rather than compartmentalizing in multiple scripts. Most of the time it's unnecessary to have multiple scripts. The memory usage will be slightly higher with multiple scripts.
More often than not, if I have multiple objects that need to interact with each other, the client/server or one-to-many/many-to-one relationship seems to be the most efficient. Instead of having 20 clients listening, have one server listening; set the clients on timers for communication to the server.
If I can close a listen that I don't need, or find a different way, I will. You just have to be creative. Writing efficient scripts isn't hard.