Categories
Uncategorized

Middleware marketing 1: Make sure your ads are targeted for Google Adwords

What I’m about to write may sound obvious, but I didn’t do it, so I think it bears stating. When advertising on Google Adwords, be sure your ads are as targeted as possible to avoid wasting money.

Originally I listed every keyword I could think of that was related to RakNet in some way. I came up with like 80 keywords, in fact Google makes it easy to do this.

I set a budget of $20 a day, and almost immediately hit my cap. The campaign optimizer suggested I increase to $100 a day. But as I previously wrote, I had no new sales nor did the forum show increased activity. About the only increased activity I got was Chinese spammers. I wasted about $300.

I went back and targeted all my ads. In the ad for example it clearly states that it’s a C++ programming library. I also disabled ads from non-relevant categories (porn, law enforcement) which are enabled by default. I also disabled ads from domain parking pages, since programmers are smart enough not to go to these pages anyway.

This dropped me down from instantly hitting $20 a day, with a recommended cap of $100, to spending a few dollars a day.

Categories
Uncategorized

10 gigabytes of requests from China?

I was looking at some strange Webalizer stats for RakNet.

This IP address 211.153.203.4 has required 10.7 gigabytes worth of data in only 5 visits. That is 10X more than the next highest IP address 91.67.34.76.

The IP address is from China.

91.67.34.76 is in Germany, and has requested 1 gigabyte in a single visit.

I’m not sure, but my guess is all those forum spammers is some gang or bot computers because I can’t see what else would use that much bandwidth.

Edit:

Webhost told me to make a .htaccess file with this list:

Deny from 211.153.203. 91.67.34.76

I tried it with my own IP, and it seems to work.

Edit 2:

After doing this yesterday, today my traffic was down by 80%! So it looks like 4 out of 5 visits were just spam bots from China trying to hack the forum. Good grief!

Categories
Game Development

Quality of service emulator

Screenshot

It uses the layered service provider system I wrote about. For any UDP based application (actually with one line of code change it work with TCP too) it will add the desired attributes to the connection.

One big snag is how to implement an incoming bandwidth throttle. There are 3 ways data can come in, nonblocking, blocking, or with IO completion ports. Nonblocking is the easiest, I just stick the data into a buffer and return it when the user later calls recv or recvfrom again. Blocking is harder. I would have to put an infinite loop in the recvfrom call and not return until the required latency has elapsed. However, you can break out of the Windows version of recvfrom with a signaled event, and I have no idea how I’d hook into that event. IO completion ports is similar to nonblocking, but the buffer has to be added to from a worker thread elsewhere. If I can’t figure this out I’d have to drop the incoming bandwidth throttle. This would have been easier if I had implemented it at the NDIS level, although it would have been harder in other ways.

Another problem is the layered transport service provided by windows is DLL and registry based. So if you were to kill the program with end process, the DLL would not be uninstalled automatically when the process shuts down. If you were to then delete the program without uninstalling it that DLL would be stuck in your system, loading up the QoS emulator when you don’t want it. I’m not sure if the DLL can unregister itself in its own startup call. If I can, I will check for the program installation in startup, and have the DLL unregister itself if it looks like the program was uninstalled.

I’m not sure all this will work on Vista either. There was some crap in the Windows SDK documentation about security and various extra things you have to do in the installer, the registry, and the program itself. I only scanned over it in passing while looking for info on the Winsock debug/trace DLL system. I hope there’s code there I can just copy/paste.

This program has been very complicated and difficult to write, partly because I’ve never done anything like it before. It requires knowledge of threads, IO completion ports, sockets and socket properties, the registry, installation settings and permissions, interprocess communication, hooking in and debugging DLLs called by the system, and complicated associations between LSPs, the high level user-code, other LSPs, and the low level transport service provider. That article by Microsoft states “You will probably find that implementing an LSP is no longer a daunting and time-consuming task if you simply extend the layered sample” but if they consider that to be easy I’d hate to see what they consider hard.

Thanks to Jason King for help designing the GUI!

Categories
Uncategorized

Dumbasses

50 Indians blind themselves searching the sky for a reported image of the Virgin Mary

Categories
Uncategorized

Google adwords less effective than before

About 3-4 years back I used Google adwords to advertise RakNet. It was a good deal then. My daily budget was $3 a day. I got $100 worth of clicks, with the average click through rate at 2% and the average cost per click at 5 cents.

At the same time I looked at regular banner advertising. It was like $1500 for one month with no guarantee of clicks at all. By an order of magnitude Google advertising was better than banner advertising. So I signed up, but due to lack of funds at the time without a proportional increase in sales I stopped it.

I’ve tried Google advertising again two weeks ago. Now I can’t even show up for the same terms, and they want $5 per click to do so! Outrageous considering 99% of people who click on an ad won’t buy anything. The average click cost is 25 cents, the daily maximum is $20 and there is a notice saying I am not receiving 79% of my eligible impressions. In other words, they want $5000 a month for what I did with $100 a month before. While I am getting clicks through the content network, I think most of those are fraudulent or not relevant. There are more guests online in the forum, but those are probably spam bots, since if they really were new users I would be getting a proportional increase in help posts, and I haven’t been. I’ve been also getting more junk email about website ranking, so that’s another sign it’s just bots.

I’ll give it another two weeks and cancel if I don’t see a justifiable increase in new user posts on the forum. No sense in paying money just to get more spam!

I’m going to also look into a banner ad on GameDev.net if the price is comparable. However, a friend who runs a major gaming site said he had to refund an advertiser’s money because it only got 3 clicks out of 2 million impressions. So I’ll have to ask them if they have any guarantee of clicks, and average number of clicks per ad.

Categories
Game Development

Networking friendly game loop with variable length updates and renders

I was reading http://dewitters.koonsolo.com/gameloop.html where the author, Koen Witters, proposes a fixed-update game loop with a variable update render loop using interpolation to find out between-frame render positions. It’s a well written article and his solution is good for single player games.


const int TICKS_PER_SECOND = 25;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;

DWORD next_game_tick = GetTickCount();
int loops;
float interpolation;

bool game_is_running = true;
while( game_is_running ) {

loops = 0;
while( GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP) { update_game(); next_game_tick += SKIP_TICKS; loops++; } interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick ) / float( SKIP_TICKS ); display_game( interpolation ); }

However, this has problems with online games. In networking, you often need to extrapolate given a prior position and some amount of time to the current time. For example, I may get a position packet 208 milliseconds ago. If I were to update every 40 milliseconds (25 ticks per second), I would have 8 milliseconds leftover. This moves the problem of left-over ticks to your game objects.

You can either calculate partial ticks, in which case your game objects are slightly out of synch with the fixed-step simulation, or you can ignore them, and just use the least number of ticks you can fit in. If you get frequent updates this is OK, but for objects that are not updated frequently things can get out of place, and a lot faster than 2.4336088699783431e-13.

My solution is variable length game updates with variable length frame updates, with a frequency limit on game updates.

Variable length updates with variable length frame updates:


// Do not skip more than one second (due to debugging)
const int MIN_UPDATE_TIME=1000;
// Do not update more than every 10 milliseconds
const int MAX_UPDATE_TIME=10;
// How much time to render forward
float renderExtrapolationTime;

bool game_is_running = true;
Time lastGameUpdate=GetTimeMS();

// Force the first ever update, before the first ever render
Time elapsedGameTime=MAX_UPDATE_TIME;
while( game_is_running ) {

if (elapsedGameTime >= MAX_UPDATE_TIME) {

if (elapsedGameTime > MIN_UPDATE_TIME)
elapsedGameTime = MIN_UPDATE_TIME;

update_game(elapsedGameTime);
lastGameUpdate=GetTimeMS();
}

renderInterpolationTime = GetTimeMS() - lastGameUpdate;
display_game( renderExtrapolationTime );
elapsedGameTime=GetTimeMS()-lastGameUpdate;
}

Categories
Uncategorized

Babies with breasts

Two close friends just had a baby together two weeks ago. Yesterday, they took the baby to the doctor because they found lumps growing on her chest. Turns out they were breasts.

My friends always buy the cheapest meat they can find from a major warehouse store, especially beef. Beef is pumped full or hormones like some chemical Frankenstein, to make the cows grow and produce milk as quickly as possible. These hormones get into the food supply, and cause many health problems

Hormones in beef linked to male fertility problems
Hormones in beef
Alarm over beef link to breast cancer
Artificial hormones in U.S. beef linked to breast cancer, prostate cancer

Chicken and other meats are no exception.

I’m trying to avoid meat and only buying organic from now on.

Categories
Game Development

Layered transport service provider

One problem I had a couple of years ago was how to write an accurate internet simulator feature for RakNet. What I have in there now is what you find in your average games – a user can intentionally add latency to outgoing messages and can randomly drop packets to simulate packetloss. But this is not accurate and not very full-featured.

Here’s a better design:

Maximum outgoing bandwidth – Represents your network card’s ability to send data through the wire.
Maximum incoming bandwidth – As above, but for incoming data
One-way trip time – The minimum time a datagram would take to get to a remote system; the base speed of the network
Per-message additional trip time – On the internet, many people are sending messages, so there will be some delay between each of your messages as other messages goes out. So this number represents the rest of the internet using the router’s bandwidth too. The effect to the sender is that as you flood the connection, your ping goes up. This is what actually happens and is how flow control is accomplished in modern reliable packet implementations (the old way used sliding windows which controlled throughput based on how fast the other system acked your messages).
Maximum router queue – This represents how much average memory each router has. Go beyond this and you start getting packetloss.
Randomly dropped packets – Due to noise on the wire
Out of order packets – As above

The problem with hardcoding this in the user level network layer is that you have to implement a control interface (changable at runtime), you have to do it on both systems, and it can be complex to implement in every circumstance. So I’m writing a layered transport service provider. This is sort of like RakNet’s plugin system, but for Winsock, and it gives you the ability to override various network events with a procedure table. This is stored as a system DLL, and installed and uninstalled by an EXE. I will have this EXE double as a control panel and will use interprocess communication to have the EXE control the invoked DLL.

By the way, to say this is complicated is understating the issue. It’s about 1000 lines of code for the installer, 10,000 lines of code to properly create a plugin that does nothing but pass the data through. You have to understand overlapped events, IO completion ports, support for versions of winsock, an entirely different set of code to install the driver on Vista (plus permission sets), you have to use .def files for export, and more. The article that I’m going by is 8,500 words long (about 20 pages) and takes hours of study to understand well enough to do anything.

After going through all this I think Shunra is justified in charging $500 for their simulator. The solution is hard to write. However, Shunra doesn’t support loopback last I contacted them. My implementation does, so I think I can sell mine to gave developers and others that want a loopback solution. Plus I can put a nice GUI on it, so you can control what is going on at runtime.

Categories
Game Development

Data structures for fun and optimization

I was updating the manual for RakNet and was reminded of how many data structures I’ve written for it.

From the manual:

DS_BinarySearchTree.h – Binary search tree, and an AVL balanced binary search tree.
DS_BPlusTree.h – BPlus tree for fast lookup, delete, and insert.
DS_BytePool.h – Returns data blocks at certain size thresholds to reduce memory fragmentation.
DS_ByteQueue.h – A queue specialized for reading and writing bytes.
DS_Heap.h – Heap data structure, includes both minheap and maxheap.
DS_HuffmanEncodingTree.h – Huffman encoding tree, used to find the minimal bitwise representation given a frequency table.
DS_HuffmanEncodingTreeFactory.h – Creates instances of the Huffman encoding tree.
DS_HuffmanEncodingTreeNode.h – Node in the Huffman encoding tree.
DS_LinkedList.h – Standard linked list.
DS_List.h – Dynamic array (sometimes improperly called a vector). Also doubles as a stack.
DS_Map.h – (Associative array) Ordered list with an per-element sort key.
DS_MemoryPool.h – Allocate and free reused instances of a fixed size structure, used to reduce memory fragmentation.
DS_OrderedChannelHeap.h – Maxheap which returns a node based on the relative weight of the node’s associated channel. Used for task scheduling with priorities.
DS_OrderedList.h – List ordered by an arbitrary key via quicksort.
DS_Queue.h – Standard queue implemented with an array
DS_QueueLinkedList.h – Standard queue implemented with a linked list
DS_RangeList.h – Stores a list of numerical values, and when the values are sequential, represents them as a range rather than individual elements. Useful when storing many values that are usually sequential.
DS_Table.h – Table with columns and rows, and operations on that table.
DS_Tree.h – Noncyclic graph
DS_WeightedGraph.h – Graph with weighted edges, used for routing via Dijkstra’s algorithm

Data structures is one of the few classes in college that has a significant real-world bearing. It’s one of the cornerstones of good design and optimization.

A few times I’ve been asked why I don’t just use STL.

1. STL can cause linker errors
2. STL uses exceptions.
3. STL doesn’t have every feature I need.
4. I don’t know how well STL is optimized, but I know exactly how well my code is optimized.
5. In college I was confused for months before I figured out when people said ‘vector’ they meant ‘dynamic array.’ It became a pet-peeve of mine.
6. In college I started writing my own data structures before I knew STL existed. None of my classes ever covered it And once I started I had momentum to keep going.
5. It’s something I find interesting and enjoy writing.

Aside from STL, of the game companies I’ve worked at, I’ve never seen any of them with as sophisticated a set of data structures as what I have in RakNet. When you need to process and track 30,000 messages a second you need heavy duty data structures like my memory-pool optimized B+ tree. Being able to support 30,000 messages vs. your standard game’s 20-30 messages a second is part of the polish you get with a dedicated mature library.

Categories
Uncategorized

In favor of nationalized health care

I’ve been trying to buy health insurance to cover myself as a private contractor. At every step where I deal with the insurance company I am reminded of the movie Sicko. I’m a healthy guy who has never had serious medical problems. I tried signing up for Health net 3 months ago. Part of the 50 page application form was to list every doctor visit in the last 6 years or so. So I put down two visits to the doctor two years ago, both for minor problems that cleared themselves up after a few days. 3 months and half a dozen phone calls later I get back a form letter asking for every imaginable detail of those doctor visits – who I saw, addresses, phone numbers, dates, treatment details, etc. It’s like if you get health insurance, you better not ever use it, because if you do you will never get insurance again. I was fed up so wrote back to them and told them to cancel my application. “I’ve already given you these details. You have authorization to look up my records. I don’t have the time or inclination to do your job for you. If this is how you treat a potential customer trying to give you money, how will you treat me when I actually need care?.”

Initially I was ambivalent about nationalized free health insurance. The free market’s incentives are to maximize profits. When it works, the way to do this is to provide the best service for the lowest possible price to attract and satisfy as many customers as possible. The government’s incentives are to satisfy their own customers, which are generally special interests or the bureaucracy itself. It’s different in every situation, but one doesn’t have to look far to find waste, fraud, or poor service where the government is concerned. Look at the lines at the post office or the DMV. There’s also the argument that when something is free you get unlimited demand. It is true this would result in longer lines and worse service compared to an ideal free market scenario.

However, after thinking this through I think nationalized health service is the correct choice. The free market doesn’t work where you have force or fraud – in theory it is the government’s job to prevent just that (although often the government is the cause of said force or fraud). Cox cable has a monopoly where I live. So when I had my cable modem installed I was forced to use their service. As a result, I had to pay $200 to lease a modem you could buy for $50, and a $300 installation fee for a guy to drop it off at my house, and the service didn’t work for a month and a half.

Does force or fraud exist in the health insurance business? I think force is an inherent part of the equation – a sick or dying person has no choice but to accept the services that are available to them. With Cox I could at least go without or move if I wanted to, but the guy in the movie who had to choose which fingers he wanted reattached had no such option. Unlike a typical business, the insurance company makes money by NOT providing service – turning down sick customers, or denying those who are already sick. So it’s undeniable that there is an incentive to commit fraud. Usually lawsuits work out fraud, but a person who has just undergone a major health problem (and paid for it themselves) usually doesn’t have the time or money to fight the insurance companies. A dead person certainly doesn’t. The only people with the resources to take on the insurance companies, the super-rich, pay for their own services anyway.

The only question that remains is will the waste, lines, and bureaucracy of the government be better than what we have now?