
前回は空間インデックスを構築しましたが、今ではこのスキルを使用して、完全に通常のハードウェアで1日に100万クエリなど、Webインターフェイスとパフォーマンスを備えたライブ(静的ではない)マップサービスを作成します。
データ
- ソースはOSMになります。
- DBMSに保存するデータ形式は、 shpfileからのシリアル化です
- テストデータとして、ロシアのデータセットを使用します
- すべてのレイヤーのうち、水域、森林、建物(水ポリゴン、植生ポリゴン、建物ポリゴン)の3つだけを取ります。 これは、テクノロジーの操作性を確認し、そのパフォーマンスを評価するのに十分です。
データ入力 。
- DBMSとして、既製のVirtuoso V7.0.0を引き続き使用します。
- 興味のあるレイヤーごとに同じ名前のテーブルを作成します。
- ジオメトリを持つlong varbinary型のフィールドは「Shape」と呼ばれます
- 既存のすべてのフィールドが保存されます。
- 新しいものが追加されます
- _OBJECTID_-レコード番号
- minx_、miny_、maxx_、maxy_-レコード範囲
- 以前と同じ方法で空間インデックスを作成します。
- 違いは、ポイントオブジェクトではなく、エリアオブジェクトがあるため、1つのオブジェクトに複数回インデックスを作成できることです。
- 最も基本的なラスター化を行います-ジオメトリに関係なく、オブジェクトの範囲全体がインデックスに入ります。 しかし、現時点では、実際のラスタライズは時期尚早な最適化であると考えています。
- 別の違いは、マップの不均一な人口です:Chukotkaのおかげで、経度は-180から+180度まで、緯度は〜40から80まで変化します。したがって、平均して1つのオブジェクトが1つのインデックスブロックになるようにブロックインデックスステップを作成します。 なぜこれが正確に説明されるのか。
- ソースデータを操作するには、開いているShapefile Cライブラリを使用します
- BLOBを操作するには、 SHPSerializeObjectおよびSHPDeserializeObject関数を追加する必要があります。これは、ネイティブのSHPWriteObjectおよびSHPReadObjectと同様ですが、メモリを操作するためのものです
- サーバーと通信するには、ネイティブのODBCインターフェイスを使用しますが、システムドライバーマネージャーをバイパスして、組み込みドライバーを使用します。
- 速度を上げるには、接続の自動コミットをオフにし、1000オブジェクトごとにコミットします
- このモードでは
- 森林の充填(〜66万オブジェクト)には1分56秒かかります
- 貯水池の満水(〜38万オブジェクト)-1分9秒
- 建物の満杯(〜530万オブジェクト)-16分18秒
Webインターフェイスのパフォーマンスの評価 。
- はい、virtuosoにはphpに似たWebインターフェースもあります。 PL / SQLに挿入されたファイルvsp(仮想サーバーページ)は、html出力を形成するストアドプロシージャに変わります。
単純なページ(test.vsp)を作成します。このページでは、カウンターを増やし、それを使用してサーバーの速度を確認します。
組み込み関数sequence_nextは、カウンターをアトミックにインクリメントし、その値を返します。<html><body> <?vsp declare cnt integer; cnt := sequence_next ('xxx.YYY.__cnt'); ?> <table width="100%" border="1"> <tr><td align="center"><?vsp= cnt ?></td></tr> </table> </body></html>
- このページを実行するには、ルートのテストフォルダー( virtuoso.iniファイルの[HTTPServer]セクションのServerRootパラメーター)に配置し、isql(isql localhost:1111 dba dba)を介してこのフォルダーからファイルを実行できるようにします。
VHOST_DEFINE(lpath=>'/test/',ppath=>'/test/',vsp_user=>'DBA');
- ページが機能することを確認します
localhost:8890/test/test.vsp
- そして、 wgetを使用して大規模に要求します
- Windows(i7、8コア)の下のデスクトップ上で、それぞれ10,000回が上記のページを要求した20の並列wget-sの作業には28秒かかりました。 そのため、1秒あたり〜7000リクエストという望ましいパフォーマンスが得られ、私たちにとっては(1日あたり100万リクエストを目指していたとしても)ボトルネックになることはありません。
地図を描く
- まず、どのようにしてデータを取得しますか? このようなもの:
for select blob_to_string(Shape) as data from xxx.YYY."water-polygon" as x, xxx.YYY."v_water-polygon_spx_enum_items_in_box" as a where a.minx = cminx and a.miny = cminy and a.maxx = cmaxx and a.maxy = cmaxy and x."_OBJECTID_" = a.oid and x.maxx_ >= cminx and x.minx_ <= cmaxx and x.maxy_ >= cminy and x.miny_ <= cmaxy do { ... }
-
xxx.YYY."water-polygon"
は、作成してデータを入力した貯水池のテーブルです。 -
xxx.YYY."v_water-polygon_spx_enum_items_in_box"
-ブロック空間インデックスとして機能する補助テーブルの上のプロシージャビュー。 実際、これは空間インデックスブロックのサイズまで機能する粗い空間フィルターです。 -
a.minx = cminx and...
呼び出しパラメータービューを設定し、 cminx ...-描画するマップフラグメントの境界線 -
x."_OBJECTID_" = a.oid
プロシージャビューから取得したデータテーブルと合成結果セットの間の結合 -
x.maxx_ >= cminx and x.minx_ <= cmaxx ...
明らかに空間的ではない場合、ジオメトリのある塊を登らないようにする中間の空間フィルター - 一緒に、これにより、サイクルの本体で、たとえば、効率よく描画する機会が与えられます。 同時に、図面自体は薄い空間フィルターと見なすことができます。
-
- 3つのデータレイヤーがあるため、各クライアント要求に対して3つのサブクエリを実行する必要があります
- スケジュールについて。 カーソルの間に直接描画するには、 C-プラグインを作成する必要があります 。 サーバーが起動時にロードする動的ライブラリであり、新しいPL / SQL組み込み関数を登録できます。
- 実際に描画するには、 GDライブラリを使用します
- 次の関数を追加します。
- img_create-指定されたサイズを描画するためのコンテキストを作成します
- img_tostr-現在のコンテキストからgifを作成します
- img_fromptr-ポインタータグを変更するための名手
- img_destroy-コンテキストを破壊する
- img_alloc_color-RGB値から色識別子を作成する
- img_draw_polyline-形状オブジェクトが保存されているブロブからポリラインを描く
- img_draw_polygone-ポリゴンでも同じ
- スポイラーの下のプラグインのコンテンツ
#ifdef _USRDLL #include "plugin.h" #include "import_gate_virtuoso.h" #define wi_inst (wi_instance_get()[0]) #else #include <libutil.h> #include "sqlnode.h" #include "sqlbif.h" #include "wi.h" #include "Dk.h" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "gd_utils.h" #include "gd/gd_lib.h" #include "shplib/shapefil.h" typedef struct img_ctx_s { int dx_; int dy_; double minx_; double miny_; double maxx_; double maxy_; double mulx_; double muly_; int black_; int red_; int green_; int blue_; int attr_; gdImagePtr img_; } img_ctx_t; caddr_t img_create_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)dk_alloc_box (sizeof (img_ctx_t), DV_STRING); ptr->dx_ = bif_long_arg (qst, args, 0, "img_create_proc"); ptr->dy_ = bif_long_arg (qst, args, 1, "img_create_proc"); ptr->minx_ = bif_double_arg (qst, args, 2, "img_create_proc"); ptr->miny_ = bif_double_arg (qst, args, 3, "img_create_proc"); ptr->maxx_ = bif_double_arg (qst, args, 4, "img_create_proc"); ptr->maxy_ = bif_double_arg (qst, args, 5, "img_create_proc"); ptr->attr_ = bif_long_arg (qst, args, 6, "img_create_proc"); ptr->img_ = gdImageCreateTrueColor (ptr->dx_, ptr->dy_); ptr->mulx_ = ptr->dx_/fabs(ptr->maxx_ - ptr->minx_); ptr->muly_ = ptr->dy_/fabs(ptr->maxy_ - ptr->miny_); ptr->black_ = gdImageColorAllocate (ptr->img_, 0, 0, 0); ptr->blue_ = gdImageColorAllocate (ptr->img_, 0, 0, 255); ptr->red_ = gdImageColorAllocate (ptr->img_, 255, 0, 0); ptr->green_ = gdImageColorAllocate (ptr->img_, 0, 255, 0); return (caddr_t)ptr; } caddr_t img_saveas_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_saveas_proc"); gdImagePtr im = ptr->img_; caddr_t fname = bif_string_arg (qst, args, 1, "img_saveas_proc"); FILE *out = fopen (fname, "wb"); if (NULL != out) { gdImageGif (im, out); fclose (out); return (caddr_t)0; } return (caddr_t)-1; } static unsigned char clip(int value) { if (value < 0) value = 0; else if (value > 255) value = 255; return value; } caddr_t img_fromptr_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { ptrlong addr = unbox(bif_long_arg (qst, args, 0, "img_fromptr_proc")); return addr; } caddr_t img_tostr_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_tostr_proc"); gdImagePtr im = ptr->img_; void *rv = NULL; caddr_t ret = NULL; int size = 0; gdIOCtx *out = gdNewDynamicCtx (2048, NULL); gdImageGifCtx (im, out); rv = gdDPExtractData (out, &size); if (NULL == rv || size <= 0) return 0; out->gd_free (out); ret = dk_alloc_box (size, DV_STRING); memcpy (ret, rv, size); gdFree(rv); return (caddr_t)box_num (ret); } caddr_t img_destroy_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_destroy_proc"); gdImagePtr im = ptr->img_; gdImageDestroy(im); /*dk_free_box (ptr);*/ return 0; } caddr_t img_draw_polyline_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_draw_polyline_proc"); gdImagePtr im = ptr->img_; caddr_t data = bif_string_arg (qst, args, 1, "img_draw_polyline_proc"); SHPObject *shp = SHPDeserialize (data); int nparts = shp->nParts; int npoints = shp->nVertices; double *px = shp->padfX; double *py = shp->padfY; int i, j; int color = bif_long_arg (qst, args, 2, "img_draw_polyline_proc"); gdImageSetAntiAliased (im, color); for (i = 0; i < nparts; i++) { long ps = shp->panPartStart[i]; long psz = (i==(nparts-1))? npoints-ps : shp->panPartStart[i+1]-ps; gdPointPtr points = (gdPointPtr)malloc(sizeof (gdPoint) * psz); for (j = 0; j < psz; j++) { points[j].x = (px[ps+j] - ptr->minx_) * ptr->mulx_; points[j].y = (ptr->attr_ & 1) ? ptr->dy_ - (py[ps+j] - ptr->miny_) * ptr->muly_: (py[ps+j] - ptr->miny_) * ptr->muly_; } for (j = 1; j < psz; j++) { /*if (points[j].x == points[j-1].x && points[j].y == points[j-1].y) gdImageSetPixel (im, points[j].x, points[j].y, ptr->blue_); else*/ gdImageLine (im, points[j].x, points[j].y, points[j-1].x, points[j-1].y, gdAntiAliased); } free (points); } SHPDestroyObject (shp); return 0; } caddr_t img_draw_polygone_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_draw_polygone_proc"); gdImagePtr im = ptr->img_; caddr_t data = bif_string_arg (qst, args, 1, "img_draw_polygone_proc"); SHPObject *shp = SHPDeserialize (data); int nparts = shp->nParts; int npoints = shp->nVertices; double *px = shp->padfX; double *py = shp->padfY; int i,j; int color = bif_long_arg (qst, args, 2, "img_draw_polygone_proc"); int bcolor = bif_long_arg (qst, args, 3, "img_draw_polygone_proc"); for (i = 0; i < nparts; i++) { long ps = shp->panPartStart[i]; long psz = (i==(nparts-1))? npoints-ps : shp->panPartStart[i+1]-ps; gdPointPtr points = (gdPointPtr)malloc (sizeof (gdPoint) * psz); for (j = 0; j < psz; j++) { points[j].x = (px[ps+j] - ptr->minx_) * ptr->mulx_; points[j].y = (ptr->attr_ & 1) ? ptr->dy_ - (py[ps+j] - ptr->miny_) * ptr->muly_: (py[ps+j] - ptr->miny_) * ptr->muly_; } gdImageSetAntiAliased (im, color); gdImageFilledPolygon (im, points, psz, gdAntiAliased); if (bcolor >= 0) { gdImageSetAntiAliased (im, bcolor); gdImagePolygon (im, points, psz, gdAntiAliased); } free (points); } SHPDestroyObject(shp); return 0; } caddr_t img_alloc_color_proc (caddr_t * qst, caddr_t * err, state_slot_t ** args) { img_ctx_t *ptr = (img_ctx_t *)bif_arg (qst, args, 0, "img_alloc_color_proc"); gdImagePtr im = ptr->img_; int r = bif_long_arg (qst, args, 1, "img_alloc_color_proc"); int g = bif_long_arg (qst, args, 2, "img_alloc_color_proc"); int b = bif_long_arg (qst, args, 3, "img_alloc_color_proc"); return box_num(gdImageColorAllocateAlpha (ptr->img_, r, g, b, 0)); } void init_shcall_gd_utils () { bif_define ("img_create", img_create_proc); bif_define ("img_saveas", img_saveas_proc); bif_define ("img_tostr", img_tostr_proc); bif_define ("img_fromptr", img_fromptr_proc); bif_define ("img_destroy", img_destroy_proc); bif_define ("img_alloc_color", img_alloc_color_proc); bif_define ("img_draw_polyline", img_draw_polyline_proc); bif_define ("img_draw_polygone", img_draw_polygone_proc); }
- これで、水域の描画は次のようになります。
declare img any; img := img_create (512, 512, cminx, cminy, cmaxx, cmaxy, 1); declare cl integer; declare bg integer; cl := img_alloc_color (img, 0, 0, 255); bg := img_alloc_color (img, 0, 0, 200); whenever not found goto nf; for select blob_to_string(Shape) as data from xxx.YYY."water-polygon" as x, xxx.YYY."v_water-polygon_spx_enum_items_in_box" as a where a.minx = cminx and a.miny = cminy and a.maxx = cmaxx and a.maxy = cmaxy and x."_OBJECTID_" = a.oid and x.maxx_ >= cminx and x.minx_ <= cmaxx and x.maxy_ >= cminy and x.miny_ <= cmaxy do { img_draw_polygone (img, data, cl, bg); } nf:; declare ptr integer; ptr := img_tostr (img); -- gif img_destroy (img); -- declare image any; image := img_fromptr(ptr); -- http_header ('Content-type: image/gif\t\n'); -- http(image); --
- ページはURLパラメータを介して座標を自分自身に渡しますが、 ネタバレの下のページの本文
<?vsp if ({?'getfile'} <> '') { http_header ('Content-type: image/gif\t\n'); -- set the header to jpg declare s_params any; s_params := deserialize (decode_base64 (get_keyword ('params', params, ''))); -- dbg_obj_print(s_params); declare "min_x" double precision; declare "min_y" double precision; declare "max_x" double precision; declare "max_y" double precision; declare "cminx" double precision; declare "cminy" double precision; declare "cmaxx" double precision; declare "cmaxy" double precision; declare "s" varchar; s := get_keyword ('minx', s_params, ''); if (s = '') cminx := min_x; else cminx := atof(s); s := get_keyword ('miny', s_params, ''); if (s = '') cminy := min_y; else cminy := atof(s); s := get_keyword ('maxx', s_params, ''); if (s = '') cmaxx := max_x; else cmaxx := atof(s); s := get_keyword ('maxy', s_params, ''); if (s = '') cmaxy := max_y; else cmaxy := atof(s); declare img any; img := img_create (512, 512, cminx, cminy, cmaxx, cmaxy, 1); declare cl integer; declare bg integer; { cl := img_alloc_color (img, 0, 0, 255); bg := img_alloc_color (img, 0, 0, 200); whenever not found goto nf; for select blob_to_string(Shape) as data from xxx.YYY."water-polygon" as x, xxx.YYY."v_water-polygon_spx_enum_items_in_box" as a where a.minx = cminx and a.miny = cminy and a.maxx = cmaxx and a.maxy = cmaxy and x."_OBJECTID_" = a.oid and x.maxx_ >= cminx and x.minx_ <= cmaxx and x.maxy_ >= cminy and x.miny_ <= cmaxy do { img_draw_polygone (img, data, cl, bg); } nf:; cl := img_alloc_color (img, 0, 255, 0); bg := img_alloc_color (img, 0, 255, 0); whenever not found goto nf2; for select blob_to_string(Shape) as data from xxx.YYY."vegetation-polygon" as x, xxx.YYY."v_vegetation-polygon_spx_enum_items_in_box" as a where a.minx = cminx and a.miny = cminy and a.maxx = cmaxx and a.maxy = cmaxy and x."_OBJECTID_" = a.oid and x.maxx_ >= cminx and x.minx_ <= cmaxx and x.maxy_ >= cminy and x.miny_ <= cmaxy do { img_draw_polygone (img, data, cl, bg); } nf2:; cl := img_alloc_color (img, 255, 0, 0); bg := img_alloc_color (img, 255, 0, 0); whenever not found goto nf3; for select blob_to_string(Shape) as data from xxx.YYY."building-polygon" as x, xxx.YYY."v_building-polygon_spx_enum_items_in_box" as a where a.minx = cminx and a.miny = cminy and a.maxx = cmaxx and a.maxy = cmaxy and x."_OBJECTID_" = a.oid and x.maxx_ >= cminx and x.minx_ <= cmaxx and x.maxy_ >= cminy and x.miny_ <= cmaxy do { img_draw_polygone (img, data, cl, bg); } nf3:; } declare ptr integer; ptr := img_tostr (img); img_destroy (img); declare image any; image := img_fromptr(ptr); http(image); -- table and display --dbg_obj_print('boom',{?'id'}); return; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <?vsp declare "min_x" double precision; declare "min_y" double precision; declare "max_x" double precision; declare "max_y" double precision; min_x := 82.; max_x := 84.; min_y := 54.; max_y := 56.; params := vector_concat (params, vector ('minx', sprintf('%g', min_x), 'maxx', sprintf('%g', max_x), 'miny', sprintf('%g', min_y), 'maxy', sprintf('%g', max_y))); ?> <html> <body zonload="window.location.reload();"> <script language="JavaScript" type="text/javascript"> function full_extent() { document.forms['form1'].minx.value=<?vsp=min_x ?>; document.forms['form1'].miny.value=<?vsp=min_y ?>; document.forms['form1'].maxx.value=<?vsp=max_x ?>; document.forms['form1'].maxy.value=<?vsp=max_y ?>; } </script> <script language="JavaScript" type="text/javascript"> function zoom_in() { var dx = Math.abs(document.forms['form1'].maxx.value - document.forms['form1'].minx.value); dx = dx/8; var tmp = document.forms['form1'].maxx.value; tmp -= dx; document.forms['form1'].maxx.value = tmp; tmp = document.forms['form1'].minx.value; tmp -= -dx; document.forms['form1'].minx.value = tmp; var dy = Math.abs(document.forms['form1'].maxy.value - document.forms['form1'].miny.value); dy = dy/8; tmp = document.forms['form1'].maxy.value; tmp -= dy; document.forms['form1'].maxy.value = tmp; tmp = document.forms['form1'].miny.value; tmp -= -dy; document.forms['form1'].miny.value = tmp; } </script> <script language="JavaScript" type="text/javascript"> function zoom_out() { var dx = -Math.abs(document.forms['form1'].maxx.value - document.forms['form1'].minx.value); dx = dx/8; var tmp = document.forms['form1'].maxx.value; tmp -= dx; document.forms['form1'].maxx.value = tmp; tmp = document.forms['form1'].minx.value; tmp -= -dx; document.forms['form1'].minx.value = tmp; var dy = -Math.abs(document.forms['form1'].maxy.value - document.forms['form1'].miny.value); dy = dy/8; tmp = document.forms['form1'].maxy.value; tmp -= dy; document.forms['form1'].maxy.value = tmp; tmp = document.forms['form1'].miny.value; tmp -= -dy; document.forms['form1'].miny.value = tmp; } </script> <script language="JavaScript" type="text/javascript"> function pan_left() { var dx = Math.abs(document.forms['form1'].maxx.value - document.forms['form1'].minx.value); dx = dx/8; document.forms['form1'].maxx.value -= dx; document.forms['form1'].minx.value -= dx; } function pan_right() { var dx = -Math.abs(document.forms['form1'].maxx.value - document.forms['form1'].minx.value); dx = dx/8; document.forms['form1'].maxx.value -= dx; document.forms['form1'].minx.value -= dx; } function pan_up() { var dy = -Math.abs(document.forms['form1'].maxy.value - document.forms['form1'].miny.value); dy = dy/8; document.forms['form1'].maxy.value -= dy; document.forms['form1'].miny.value -= dy; } function pan_down() { var dy = Math.abs(document.forms['form1'].maxy.value - document.forms['form1'].miny.value); dy = dy/8; document.forms['form1'].maxy.value -= dy; document.forms['form1'].miny.value -= dy; } </script> <form method="GET" id="form1" name="form1"> <?vsp declare "cminx" double precision; declare "cminy" double precision; declare "cmaxx" double precision; declare "cmaxy" double precision; declare "s" varchar; s := get_keyword ('minx', params, ''); if (s = '') cminx := min_x; else cminx := atof(s); s := get_keyword ('miny', params, ''); if (s = '') cminy := min_y; else cminy := atof(s); s := get_keyword ('maxx', params, ''); if (s = '') cmaxx := max_x; else cmaxx := atof(s); s := get_keyword ('maxy', params, ''); if (s = '') cmaxy := max_y; else cmaxy := atof(s); declare mashtab double precision; mashtab := floor((cmaxx-cminx)*96./(512.*2.54)); declare cnt integer; cnt := sequence_next ('xxx.YYY.__cnt'); ?> <input type="hidden" name="minx" value='<?vsp=cminx ?>'/> <input type="hidden" name="miny" value='<?vsp=cminy ?>'/> <input type="hidden" name="maxx" value='<?vsp=cmaxx ?>'/> <input type="hidden" name="maxy" value='<?vsp=cmaxy ?>'/> <table width="100%" border="1" cellpadding="0" cellspacing="0" summary=""> <tr> <td width="20%" align="center" > </td> <td width="20%" align="center" >Min X</td> <td width="20%" align="center" >Min Y</td> <td width="20%" align="center" >Max X</td> <td width="20%" align="center" >Max Y</td> </tr> <tr> <td width="20%" align="center" >Default extent</td> <td width="20%" align="center" > <?vsp=min_x ?> </td> <td width="20%" align="center" > <?vsp=min_y ?> </td> <td width="20%" align="center" > <?vsp=max_x ?> </td> <td width="20%" align="center" > <?vsp=max_y ?> </td> </tr> <tr> <td width="20%" align="center" >Current extent</td> <td width="20%" align="center" > <?vsp=sprintf('%10.3f', cminx) ?> </td> <td width="20%" align="center" > <?vsp=sprintf('%10.3f', cminy) ?> </td> <td width="20%" align="center" > <?vsp=sprintf('%10.3f', cmaxx) ?> </td> <td width="20%" align="center" > <?vsp=sprintf('%10.3f', cmaxy) ?> </td> </tr> <tr> <td width="20%" align="center" > </td> <td width="20%" align="center" > <input type="button" onclick="javascript: full_extent(); document.forms['form1'].submit ();" value="[*]"/> </td> <td width="20%" align="center" > <input type="button" onclick="javascript: zoom_in(); document.forms['form1'].submit ();" value="+" /> <br><input type="button" onclick="javascript: zoom_out(); document.forms['form1'].submit ();" value="-" /> </td> <td width="20%" align="center" > <input type="button" onclick="javascript: pan_up(); document.forms['form1'].submit ();" value="^" /> <br> <input type="button" onclick="javascript: pan_down(); document.forms['form1'].submit ();" value="V" /> </td> <td width="20%" align="center" > <input type="button" onclick="javascript: pan_left(); document.forms['form1'].submit ();" value="<" /> <input type="button" onclick="javascript: pan_right(); document.forms['form1'].submit ();" value=">" /> </td> </tr> <tr><td colspan=5 align="center"> <p><img src=""></p> </td></tr> </table> </form></body></html>
- 結果は次のとおりです。
パフォーマンス評価。
- これは、Webインターフェイス自体を調べたときとほぼ同じ方法で行います。
- 4つのwgetを並行して開始します。各wgetは、ページと画像に対して10,000ペアのリクエストを作成します。 1つのwget内では、リクエストは同じですが、リクエストは異なります。 これは多くのデータが存在しないという事実のために行われ、何らかの方法でデータがメモリに保存されますが、リクエストをランダムにすると、評価が困難なウォームアップ時間が発生します。 そして、すべてのリクエストが同じように行われた場合、肘でプッシュされ始めます 誰もトランザクション要件をキャンセルしませんでした。
- なぜなら バックグラウンドでプロセスを開始した後、バリア(bashで待機)があり、最も遅い要求で測定が実行されます。
- リクエストはそれほど大きくはありません〜3X3 km、
- 注意深い読者は、これらのテストはインデックス設定に合わせて調整されており、普遍性がないと言うでしょう。 はい、そうです。 ブロックインデックスの性質は、セルサイズに見合ったクエリでのみ効果的に機能するようなものです。 これは一方でです。 そしてもう一方には、
異なるマップ縮尺に対して複数のブロックインデックスを同時に使用することを禁止する人はいません。 さらに、ブロックウェッジはブロックインデックスに収束しませんでした。 範囲を4次元のポイントと見なす場合、たとえば、 ポイントインデックスを使用できます 。
- したがって、合計稼働時間は8分12秒です。 または1秒あたり81リクエスト。
- 100万件のリクエストには3時間32分かかります。 重大な劣化はありません。
- ネットワークを通るデータフロー-52 Mbpsは半分に分割する必要があります。 同じホストにクライアントとサーバーの両方があります
- CPU使用率-68%、サーバーは66を占有
- サーバーは1.1〜1.6 GBのRAMを使用し、明らかにリークはありません。いずれの場合でも、100万のリクエストの後、1.3 GBが使用されました
- データベースファイルサイズ-〜3 GB
結論
- パフォーマンスの目標は達成され、経験によれば、1日あたり100万件のリクエストが簡単に処理され、ピーク負荷に対して十分なマージンがあることが示されています。
- デスクトップウィンドウはサーバーOSではないという事実にもかかわらず
- そして、ハードウェアはサーバーではありませんでした
- プロトタイプさえ提示されているのではなく、技術実証者が提示されていることに注意すべきです。 かなりの数ではありますが、3つのレイヤーのみが使用されました。 もちろん、実際には何十もの層がありますが、すべてが同時に必要なわけではありません。 生活を楽にするために、一般化されたレイヤーが小規模で使用されます。 等 など しかし、繰り返しになりますが、タスクはOSMを繰り返すことではなく、テクノロジーの操作性を確認することだけでした。
- インターフェイスが...禁欲的であると思われる場合は、前の段落を参照してください。
- 実装されていないラベル...
- 実装されていない投影...
- このテクノロジーの重要な機能は、PL / SQLテキスト形式のマッププロジェクトの必須記述です。 これには欠点もありますが、明確なプラスもあります-柔軟性と完全な行動の自由。 したがって、完全なGISのパワーとタイルの静的ピラミッドのパフォーマンスを備えたシステムを実装できます。 たとえば、交通標識の上に道路の署名を開始します。