Files
openstreetmap-mod_tile-pyth…/speedtest.cpp
Kai Krueger e8001c859f Add support for pluggable storage backends to mod_tile / renderd
So far, (meta)tiles could only be stored and retrieved from a locally mounted posix filesystem.  Although, the posix
filesystem API is it self a plugable storage layer into which one can mount many different filsystems, from temporary
filesystems to network filesystems, as mod_tile installations scale up to multi-server environments this might not be sufficient and one
may want to use other storage layers.

This patch therefore abstracts all storage calls out into a separate API that can be implemented by various storage backends to fit the needs of different
installations. 

Three storage backends are included in this commit:

- file backend: This is the equivalent of what existed before in mod_tile / renderd. This uses a posix filesystem to store (meta)tiles
- memcached: This stores tiles in a memcached store
- rados: This stores tiles in a rados / ceph cluster

The memcached and rados backends should currently still be considered as experimental

There are also other refactoring and cleanups in this commit
2013-03-23 22:19:30 +00:00

289 lines
7.2 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <poll.h>
#include <errno.h>
#include <math.h>
#include <limits.h>
#include <string.h>
#include <strings.h>
#include <getopt.h>
#include "gen_tile.h"
#include "protocol.h"
#include "render_config.h"
#include "render_submit_queue.h"
#define DEG_TO_RAD (M_PI/180)
#define RAD_TO_DEG (180/M_PI)
#ifndef METATILE
#warning("Speed test not implemented for non-metatile mode. Feel free to submit fix")
int main(int argc, char **argv)
{
fprintf(stderr, "Speed test not implemented for non-metatile mode. Feel free to submit fix!\n");
return -1;
}
#else
static const int minZoom = 0;
static const int maxZoom = 18;
#if 1
static double boundx0=-0.5;
static double boundy0=51.25;
static double boundx1=0.5;
static double boundy1=51.75;
#endif
#if 0
// bbox = (-6.0, 50.0,3.0,58.0)
static double boundx0=-6.0;
static double boundy0=50.0;
static double boundx1=3.0;
static double boundy1=58.0;
#endif
#if 0
// UK: 49.7,-7.6, 58.8, 3.2
static double boundx0=-7.6;
static double boundy0=49.7;
static double boundx1=3.2;
static double boundy1=58.8;
#endif
static double minmax(double a, double b, double c)
{
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
a = MAX(a,b);
a = MIN(a,c);
return a;
}
class GoogleProjection
{
double *Ac, *Bc, *Cc, *zc;
public:
GoogleProjection(int levels=18) {
Ac = new double[levels];
Bc = new double[levels];
Cc = new double[levels];
zc = new double[levels];
int d, c = 256;
for (d=0; d<levels; d++) {
int e = c/2;
Bc[d] = c/360.0;
Cc[d] = c/(2 * M_PI);
zc[d] = e;
Ac[d] = c;
c *=2;
}
}
void fromLLtoPixel(double &x, double &y, int zoom) {
double d = zc[zoom];
double f = minmax(sin(DEG_TO_RAD * y),-0.9999,0.9999);
x = round(d + x * Bc[zoom]);
y = round(d + 0.5*log((1+f)/(1-f))*-Cc[zoom]);
}
void fromPixelToLL(double &x, double &y, int zoom) {
double e = zc[zoom];
double g = (y - e)/-Cc[zoom];
x = (x - e)/Bc[zoom];
y = RAD_TO_DEG * ( 2 * atan(exp(g)) - 0.5 * M_PI);
}
};
static GoogleProjection gprj(maxZoom+1);
void display_rate(struct timeval start, struct timeval end, int num)
{
int d_s, d_us;
float sec;
d_s = end.tv_sec - start.tv_sec;
d_us = end.tv_usec - start.tv_usec;
sec = d_s + d_us / 1000000.0;
printf("Rendered %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec);
fflush(NULL);
}
int rx_process(const struct protocol *req)
{
fprintf(stderr, "version(%d), cmd(%d), z(%d), x(%d), y(%d)\n",
req->ver, req->cmd, req->z, req->x, req->y);
return 0;
}
int process_loop(int fd, int x, int y, int z, const char * map)
{
struct protocol cmd, rsp;
//struct pollfd fds[1];
int ret = 0;
bzero(&cmd, sizeof(cmd));
cmd.ver = 2;
cmd.cmd = cmdRender;
cmd.z = z;
cmd.x = x;
cmd.y = y;
strcpy(cmd.xmlname, map);
//strcpy(cmd.path, "/tmp/foo.png");
//printf("Sending request\n");
ret = send(fd, &cmd, sizeof(cmd), 0);
if (ret != sizeof(cmd)) {
perror("send error");
}
//printf("Waiting for response\n");
bzero(&rsp, sizeof(rsp));
ret = recv(fd, &rsp, sizeof(rsp), 0);
if (ret != sizeof(rsp)) {
perror("recv error");
return 0;
}
//printf("Got response\n");
if (!ret)
perror("Socket send error");
return ret;
}
int main(int argc, char **argv)
{
const char *spath = RENDER_SOCKET;
int fd;
struct sockaddr_un addr;
int ret=0;
int z;
int c;
char name[PATH_MAX];
struct timeval start, end;
struct timeval start_all, end_all;
int num, num_all = 0;
const char * mapname = "default";
int verbose = 0;
int numThreads = 1;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"socket", 1, 0, 's'},
{"num-threads", 1, 0, 'n'},
{"map", 1, 0, 'm'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hvs:m:", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 's': /* -s, --socket */
spath = strdup(optarg);
break;
case 'm': /* -m, --map */
mapname=strdup(optarg);
break;
case 'v': /* -v, --verbose */
verbose=1;
break;
case 'n': /* -n, --num-threads */
numThreads=atoi(optarg);
if (numThreads <= 0) {
fprintf(stderr, "Invalid number of threads, must be at least 1\n");
return 1;
}
break;
case 'h': /* -h, --help */
fprintf(stderr, "Usage: speedtest [OPTION] ...\n");
fprintf(stderr, " -m, --map=MAP render tiles in this map (defaults to '" XMLCONFIG_DEFAULT "')\n");
fprintf(stderr, " -s, --socket=SOCKET unix domain socket name for contacting renderd\n");
fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default 1)\n");
return -1;
default:
fprintf(stderr, "unhandled char '%c'\n", c);
break;
}
}
fprintf(stderr, "Rendering client\n");
spawn_workers(numThreads, spath, 1000);
// Render something to counter act the startup costs
// of obtaining the Postgis table extents
printf("Initial startup costs\n");
gettimeofday(&start, NULL);
enqueue(mapname, 0, 0, 0);
gettimeofday(&end, NULL);
display_rate(start, end, 1);
gettimeofday(&start_all, NULL);
for (z=minZoom; z<=maxZoom; z++) {
double px0 = boundx0;
double py0 = boundy1;
double px1 = boundx1;
double py1 = boundy0;
gprj.fromLLtoPixel(px0, py0, z);
gprj.fromLLtoPixel(px1, py1, z);
int x, xmin, xmax;
xmin = (int)(px0/256.0);
xmax = (int)(px1/256.0);
int y, ymin, ymax;
ymin = (int)(py0/256.0);
ymax = (int)(py1/256.0);
num = (xmax - xmin + 1) * (ymax - ymin + 1);
// if (!num) {
// printf("No tiles at zoom(%d)\n", z);
// continue;
// }
printf("\nZoom(%d) Now rendering %d tiles\n", z, num);
num_all += num;
gettimeofday(&start, NULL);
for (x=xmin; x<=xmax; x++) {
for (y=ymin; y<=ymax; y++) {
enqueue(mapname, x, y, z);
}
}
wait_for_empty_queue();
//printf("\n");
gettimeofday(&end, NULL);
display_rate(start, end, num);
}
finish_workers();
gettimeofday(&end_all, NULL);
printf("\nTotal for all tiles rendered\n");
display_rate(start_all, end_all, num_all);
return ret;
}
#endif