内科(2)-分類

 情報技術に関するコードの分類について、述べます。

  1. 画面系コード
  2. 情報系コード
  3. 運用、バッチ系コード

 画面系は、javaとかVisual C++とか画面に表示したり、入力を受け付けたりするもので、情報系はデータベースから情報を取得したり、保存したりします。運用、バッチ系はバックアッ プや古いデータの削除といったメンテナンスだったり、データ集計処理といった業務向けの処理だったりします。それぞれの特徴を理解する事で、障害や改造前 のレビューなどに生かせると思います。

【1.画面系コード】

 人が作って、人が操作しますので、改造が多く、また、チェック機能が漏れやすく、誤った使い方ができてしまう代物です。また、1ユーザが使用するよ うに作るので、処理としては比較的軽いのですが、何万ユーザが同時に使用するとサーバダウンという重大な障害につながる事があります。プログラマーがしが ちなのは、安易な改造で処理を重くしてしまうという事です。コードをいじる人は上級SEと違い、何人で使用するとか、あまり気にしない傾向がありま す。新規開発ではリリース前に性能試験を実施し、どこまでの利用に耐えられるかを予め、確認する工程がありますが、改造の場合はなかなかできません。本番 と同じ機器を用意する事も困難ですし、本番環境にテストデータを入れるのも、手間がかかります。とはいえ、放っておくわけにはいかないので、負荷が なくても計測はしておくべきです。処理が重くなるとはどういう事かというと、リソース(CPU、メモリ、ディスク、トラフィック)を食いつぶし、競合して 割り振りがはじまり遅くなるという事です。食いつぶし段階はまだ、影響はありませんが、競合し始めるとガクッと性能が落ちます。例えばサーバ全体でCPU やメモリを50%使っていたとします。その中で動かしているプログラムが改修前で、CPU、メモリを1%使って使用し、改造後に2%使うようになってた ら、リリースした後にシステムは停止します。本番環境と違う環境だっとしても改修前後で何倍になるかは理解しておくべきです。unixであれば、ps コマンドで確認できますし、windowsでもタスクマネージャで確認する事ができます。最近はマルチスレッドなので、プロセス単位の中にさらに複数起動 している場合がありますが、何スレッド動いているかなど、調べる方法はあります。

 必ずではありませんが、主にリソースを使用する要因について、述べます。

  • CPU使用率

 これは、大きく、SYS部分とUSER部分に分かれます。SYS部分は、OSとのやり取りのうち、割り込み、計算、分岐、マルチプロセス、マルチスレッドといったところにかかります。USER部分は、メモリIO、ディスクIOにかかります。WEBサーバの場合、マルチプロセスやスレッドで同時並行に動かします。極端に接続ユーザが増えるとSYS部分が割り込みや制御というところで使い始め、USER部分は個々のプロセスやスレッドのIO部分で使用しますので、どちらか一方が極端に増えるというのはあまりなく、SYSもUSERも同じように上がってくる傾向になります。監視のグラフ表示を実施し、ある時期から極端にSYSを使い始めた、またはUSERを使い始めたという現象は、問題があるでしょう。SYS部分で気になるのは、処理を追加した際に想定以上にループが発生しているのではないか。USER部分が増えた場合は、データベースから取得したデータ量が想定以上になっているのではないか。そんな見方ができますが。一番やっかいなのは、何もしてないのに、増えた場合です。ある日を境に異常になる場合はあります。もともと埋め込まれていたものが、原因ではあるのですが、手掛かりが少ないので特定するのは難しいです。例えば、バックアップ領域が不足し、バックアップできず、削除もできなくなった場合があります。削除できずに日に日に参照するデータ量が増えていく。バックアップ先が同じサーバ上であれば、気づくかもしれませんが、外部ストレージで監視が弱かったりすると発生箇所、直接の原因が離れている為、見つけるのに時間がかかります。

  • メモリ使用率

 メモリはスワップ、バッファ、キャッシュという3つのくくりになります。スワップは、メモリではありません。メモリ使用量が100%になった時、機能の正常性を保つ為、ディスク上にメモリと同様の空間を用意していて、そこを使用している事をさします。スワップ領域は使われていないのが正常な状況です。ディスクを使用しているので当然、遅くなります。(最近は、SSDというメモリのディスクもあります) ただ、スワップはバッファ、キャッシュにメモリを使い果たされた状態をさすだけですので、何に使われたかを示すものではありません。バッファは、ディスクIOがボトルネックとなった場合にディスクに書き込まれる間、メモリ上に一時的に保管しています。これはディスクIOが常に高負荷状態では意味がなく、負荷に波がある場合に平坦化するものです。内蔵ディスクをRAIDで組んでいる時に、ディスクが中途半端に壊れると、RAIDコントローラは異常に気付かず、ディスクは何度も違う場所への再書き込み繰り返すという現象に出会った事があります。こいう場合は、あっという間にバッファが使い果たされます。その時の対処方法は、ディスクIOのREDが点灯し続けているディスクを抜くというなんとも言えない対応でした。キャッシュは、CPUの命令や、CPUと主記憶装置間のバス上のデータといったようにCPUに近いとこで使用されます。ディスクIOというよりは演算やループによる演算の繰り返しにより消費します。概要でも述べましたが、全てのコードを見て利用しているわけではないので、中身を理解せずにコードに追加してしまうとこの現象に陥る事があります。コードの実行状況を把握する為に、ログを出力するコードを追加する事があります。ループの外側であれば、良いのですが、秒間1000回とか10000回とかループするところに入れてしまうとバッファとキャッシュの両方使い果たすという事がありました。ログを出力するようにした後に性能試験をしないと本番の使用状況に耐えられなくなる。しかも、原因を特定する為に入れた行為があだとなる悲しい状況になります。

【2.情報系コード】

 これは今でもデータベースが主流になり、そこで使われるデータベース専用のコード(SQL)について、述べます。データベースとは、大量のデータから如何に早く目的のデータにたどり着くかを目的として考えられた概念です。最大の特徴は、インデックスデータです。インデックスはその名のとおり、本の最後に書かれていて索引とも言われます。(英語か日本語かの話ですけど。。)1000ページの本の中から「か行」の「いの段」である「き」で始まる名称は何か、また、その「き」で始まった名称は、本のどこのページに書かれているかがインデックスを見れば、すぐに場所を特定する事ができます。という事は、逆にいうとインデックスの作り方や使い方次第、パフォーマンスが大きく変わってきます。本文が1000ページあって、インデックスが800ページあったら、どうでしょう。というかそんなインデックスは使えないのですが、結構、みかけます。もう一つ、データベースにはテーブルという概念があり、テーブル毎にインデックスを作る事ができます。どんなに小さなシステムでは10テーブル、大きなシステムになると1000テーブルとか存在してきます。さきほどの例にならうと、本が10冊だったり1000冊だったりするわけですが、データベースでは複数の本を連携させて目的のデータを取得する事ができます。これも、また2冊のインデックスを照らし合わせながら、見る分にはいいのですが、10冊を連携していたとなると連携する分、遅くなります。住所名簿があり、人口分布図があり、年代別年収平均表があった場合に年収500万の人がたくさん密集している場所の「中澤」という名前はものは、どこに住んでいるか。個人的には興味がありますが、3冊を照らし合わせるのは大変です。この場合のセオリーは、この3冊の中で一番分厚い本から見ていく事です。この場合は細かさもありますが、名簿が一番分厚いとして、名簿から「中澤」の情報を取得します。あとは、中澤の住所から分布情報をくっつけ、年齢から年収をくっつけます。3冊同時にいくか1冊づつ行くかは、性能を見ながら決める事になります。というのは、「中澤」という名前は多くないからいいのですが、「佐藤」「鈴木」といった場合は、最初の名簿で絞り切れず、多い分、人口分布や年代別年収表を繰り返しみる事になるからです。これは、本の構成やデータベースの概念を知っている事は当たり前ですが、本の中がどのようになっているかがわかっている必要があります。わからないからデータベースが補うのだろ、といいたいところですが、データの中身を知らないと思わぬ落とし穴にあいます。特にITですから、データの構成を理解する事は非常に重要です。地味な作業なのですが、システムを更改する際にデータ移行という工程があります。私も何度もやってきましたが、データ移行をやると取り扱うデータを理解するのに最適です。データ移行は、なぜか整理したいとか、そんな情報は使っていないという思いの念に左右され、実は使ってるし、とか、わけのわからない情報で、後々必要だったという事がよくあります。人は罪深い存在です。ですが、取りこぼしは一切できない事を肝に銘じて取り掛かっています。あとで見つかると、どんどん本の構成が崩れ、インデックスの量が増え、性能を上げることなどできなくなります。

【3.運用、バッチ系コード】

 もっとも人に近いコードと言えます。ですので、システムを長く使えば使うほど、増殖します。他のコードで補えなかったものをここで補うのは、開発当初は想定できなかった事が以外と多いからです。私の兄は、若いころボランティアとして海外に行っていました。一番最初に覚える言葉は「トイレどこですか」だそうです。空港でも、道端でもその場でするわけにはいかないので、なるほどと思いました。システムを開発し、サービス提供して、日々運用するのですが、開発の初期である設計において、どれほど、決めなければいけない項目があるか、海外に行ってみなければ、ここでは、運用が始まらないとわからないという事です。家族旅行で忘れ物をする人は、設計段階で必要な事を全て伝えたはあり得ないでしょう。そんな状況に応える為に、比較的簡単にコードを書けるものが、使用されます。目的は如何に早くコードを書き、動かすかです。書く行数も少ない方が書きやすいので、1行でできる事が多くなります。多くなるという事は、あまり性能が良くないという事と、みずらい事につながります。何度も例にだしてしまいますが、不要ファイルの削除処理に性能はいりません。性能の高いコードで、最初の手続きを書いている時間はないので、「Aファイルを削除する」「Bファイルを削除する」と書けるものを選びます。時間がたって「Cファイルを削除する」という風に書き足されていきます。そのうち、Aファイルってなんだっけ。あるいは、もうAファイルは存在してないよね。という分に忘れ去られていく傾向も持ち合わせています。設計書とコードの乖離もひどくなってきます。このコードで問題になるのは、1、や2、と違いうまく動かなくてもシステムとして問題にはならない場合があるという点です。影響が少ないという事は、安易に変更されやすくなります。そして、大問題になる事がやってきます。いらないと思うファイルを消してしまった。他は変更したけど、これは使っていないから、同じような変更はしなかった。こと、システムにおいて無駄な事はしません。ですから不要という判断は非常に危険です。それでも他の要因で消さなければいけない状況になった時、どうするかというと見極める事です。なぜ不要になったか、それは、別なファイルに似たようなコードが書かれていて、しばらく並行で使用していたが、完全移行したような形跡が残っている。人はどういう時に作り、整理するのか。整理しようとして断念する事はよくある。そういう心理を想像できない人は、このコードに手を出すべきではないでしょう。