過去の桐井戸端BBS (桐ver.9)
24409 「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? とまと 2004/01/26-20:59
とまとです。いつも参考にさせていただいています。
管理工学研究所のホームページから「暦」をダウンロードして、
それに自作のアプリを組み込んで「貸室管理」の運用をしております。
このたび、「繰り返し」コマンドを使ってイベントを修正しました。
長くなりますけれど、その一部を掲載させていただきます。

これは一週間の「利用案内」を出力するもので、予約の入っている貸室には
その時間帯(午前、午後、夜間)ごとに「予約済」と表示するものです。

プログラムの行数は以前のものに比べてはるかに短縮されたのですが、
それに反して処理時間が長くなりました。

「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか?

手続き定義開始 利用案内()
表 予約台帳
 条件(#行集計状態=1) 行集計解除
 条件(#絞り込み状態<>0 .or#整列状態<>0) 解除 *
 絞り込み [使用日付]>=&暦の基準日
 絞り込み [使用日付]<=#日数加算(&暦の基準日,6)
 ケース開始
  ケース (#曜日(&暦の基準日)<>"日")
   メッセージボックス "利用案内","日曜日を指定してください。" , \
               アイコン=!,ボタン指定=1,制御文字展開=する
   絞り込み解除 *
   手続き終了
 ケース終了
 並べ替え {[使用日付]昇順}
 書き出し 表,"予約台帳work.tbl",終了状態=&終了, \
      {[使用日付],[行事名],[室コード],[時間区分]}
 解除 *
 終了 表 編集対象表
表 週間使用詳細
 条件(#行集計状態=1) 行集計解除
 条件(#絞り込み状態<>0 .or#整列状態<>0) 解除 *
 行削除 *
 表整理 余白割合=10
 読み込み 表,"利用案内work.tbl",編集表=しない,
      {[使用日付],[行事名],[室コード],[時間区分]}
表 利用案内
 条件(#行集計状態=1) 行集計解除
 条件(#絞り込み状態<>0 .or#整列状態<>0) 解除 *
 繰り返し &検索項目番号=#項目番号("貸室01午前行事"), \
       #項目番号("貸室20夜間行事")    /*注1*/
置換 &検索項目番号=""             /*注2*/
  併合 "週間使用詳細.tbl",置換,編集表=しない, \
     {[曜日]照合,&検索項目番号 複写2}   /*注3*/
  絞り込み &検索項目番号<>#未定義
置換 &検索項目番号="予約済"         /*注4*/
  絞り込み解除 1
 繰り返し終了
 レポート印刷 "利用案内.rpt",編集表=する,プレビュー=する
 終了 表 編集対象表
手続き定義終了

※以前の記述
注1 「繰り返し」コマンドは使用していない。
注2 置換[貸室01午前行事]=””,・・・・[貸室20夜間行事] /*60項目*/
注3 併合 “週間利用詳細.tbl”,置換,編集表=しない,\
      {[曜日]照合,[貸室01午前行事]複写2,・・・・,\
       [貸室20夜間行事]複写2}         /*60項目*/
注4 絞り込み [貸室01午前行事]<>””
   置換 [貸室01午前行事]=”予約済”
   絞り込み解除 1
      ・
      ・
   絞り込み [貸室20夜間行事]<>””
   置換 [貸室20夜間行事]=”予約済”
   絞り込み解除 1                 /*180行*/


24411 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? とまと 2004/01/26-21:57
記事番号24409へのコメント

>表 週間使用詳細
> 条件(#行集計状態=1) 行集計解除
> 条件(#絞り込み状態<>0 .or#整列状態<>0) 解除 *
> 行削除 *
> 表整理 余白割合=10
> 読み込み 表,"利用案内work.tbl",編集表=しない,
>      {[使用日付],[行事名],[室コード],[時間区分]}
>
【訂正】
読み込み 表,"利用案内work.tbl",・・・・は
読み込み 表,"予約台帳work.tbl",・・・・の誤りです。

よろしくお願いします。

とまと

24413 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? 悲しげ 2004/01/26-23:03
記事番号24409へのコメント
どもっ、とまとさん
一般的に、一括処理コマンドで「繰り返し」ループを使うよりも、
例えば内部処理である「置換」等で済ませる方が速いことは確かですが、
この場合に遅くなったのは、直接そのためでもないと思います。
そうではなくて、置換や併合を1回で済ませるか、60回づつやるかと云う
ことであって、これは当然ながら60回の方が遙かに遅くなります。(^^;)

速さを優先させたいのなら

注2 置換[貸室01午前行事]=””,・・・・[貸室20夜間行事] /*60項目*/
注3 併合 “週間利用詳細.tbl”,置換,編集表=しない,\
      {[曜日]照合,[貸室01午前行事]複写2,・・・・,\
       [貸室20夜間行事]複写2}         /*60項目*/

の記述はそのまま活かす方がよいと思います。置換も併合も1回だけですから。
この時、項目名を項目番号変数で指定してもいいが、
さほどの記述簡素化にはならないような気がしないでもありません。
あと、併合に先だって、編集対象表の方で索引を指定しておけば、
さらに幾分速くなると思います。

簡素化できるのは、この次。

注4 絞り込み [貸室01午前行事]<>””
   置換 [貸室01午前行事]=”予約済”
   絞り込み解除 1
      ・
      ・
   絞り込み [貸室20夜間行事]<>””
   置換 [貸室20夜間行事]=”予約済”
   絞り込み解除 1                 /*180行*/

ここは

 置換 [貸室01午前行事]=#cond([貸室01午前行事],[貸室01午前行事],1,"予約済") \
    ,・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ \
    ,・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ \
    ,[貸室20夜間行事]=#cond([貸室20夜間行事],[貸室20夜間行事],1,"予約済")

のようにできます。

※ [貸室云々]=#cond([],[],1,"予約済")  のような記述も可能かも(未確認)。

あと、横長の60項目だかを縦に展開して処理する方法もあり得るかもしれないが、
私の桐はv9sp1だし、中味もよく判らないので未検討。

24415 一部改良? 悲しげ 2004/01/26-23:15
記事番号24413へのコメント
注2 置換[貸室01午前行事]=””,・・・・[貸室20夜間行事] /*60項目*/

この部分は次のように書き換えられそうです。

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
行削除 *,圧縮
繰り返し &i=1,7
 &曜日=#対応文字列("日,月,火,水,木,金,土",&i)
 行追加 [曜日]=&曜日
繰り返し終了
並べ替え 索引名="曜日順" /*索引があればの話ですが*/
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

変数 &i &曜日 は宣言済とします。
この繰り返しループは7行の追加だけだから瞬時だと思います。

24416 置換や併合を繰り返しているためでしょう 佐田 守弘 2004/01/26-23:28
記事番号24409へのコメント
とまとさん
大筋は悲しげさんが書かれている通りです。
トマトさんが書かれている一括処理(ないしイベント)では、1つずつの項目について置換や併合を繰り返しております。
これが処理時間が長くなった原因です。

●今回は繰り返しコマンド自体が原因ではない
繰り返しコマンドは、文字どおり繰り返すわけですから、繰り返しの回数だけ時間が掛ります。
一般論的にいえば、1個ずつ10回繰り返すのと、10個一度に行うのとどちらが速いのか?
という問題に帰着します。
1個ずつ行うのに比べて、10個まとめて行うと10倍の時間が掛る処理であれば、結果は同じです。
しかし、行っているのは置換や併合のコマンドですから、この点で様子が違います。

●置換コマンドについて
桐の表のデータは、内部的にはちょうど表に書かれている様な順序、
つまり、1行ずつ横並びのデータが、行の順に横につながっています(ちょっと違う部分がありますがその様なイメージです)。
これはちょうど、テープに横並びで書いてあるのと同じです。
ですから、1レコードの1つの項目を置換しても、複数項目をまとめて置換しても、さほど時間は変わりません。
しかし1項目ずつの置換を繰り返すと、ちょうどかセットテープで言えば、終りまで行ったら、
巻戻さなければならないのと同じで、手数が掛ります。
これが置換コマンドを繰り返すと時間が掛る理由です。

●併合は複雑だけどほぼ同じ理由
併合は置換に比べるとより複雑な処理をしておりますが、繰り返すと遅くなる理由はほぼ同じです。
併合の場合、併合元表の照合項目と同じ値を併合先の表から検索し、検索できたら指定された処理を行います。
これを併合元のレコードについて上から順に繰り返します。
併合元のテープから1つずつ併合先のテープの頭を探してダビングを繰り返すのと同じです。
そういった複雑な処理を1度で済ませずに何回も繰り返せば、時間が掛ります。

そしてこれらは繰り返しコマンドを使わなくても、置換コマンドなどを何回も書き並べても同じ事が起きます。
この様な処理は、全レコードに対して1回で済ませるのが時間を短縮するコツです。

佐田守弘(KS-00119)
24422 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? うにん 2004/01/27-12:26
記事番号24413へのコメント

>簡素化できるのは、この次。
>
>注4 絞り込み [貸室01午前行事]<>””
>   置換 [貸室01午前行事]=”予約済”
>   絞り込み解除 1
>      ・
>      ・
>   絞り込み [貸室20夜間行事]<>””
>   置換 [貸室20夜間行事]=”予約済”
>   絞り込み解除 1                 /*180行*/

ここは、未定義でない項目値を(内容に関わらず)"予約済"に置換しているのですから、

> 置換 [貸室01午前行事]=#cond([貸室01午前行事],[貸室01午前行事],1,"予約済") \
>    ,・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ \
>    ,・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ \
>    ,[貸室20夜間行事]=#cond([貸室20夜間行事],[貸室20夜間行事],1,"予約済")

だと処理が違います。(これは未定義でない項目値はそのままにしていますよ)

置換 [貸室01午前行事]=#cond([貸室01午前行事],"予約済") \

でしょう。

>あと、横長の60項目だかを縦に展開して処理する方法もあり得る

貸室が61になったりしたらシステムを全部作り直さないといけないので、
普通はそういう風に(縦に)作るでしょうね。仕様として「対応室数は60まで」で済むなら問題ないですが。

一括処理の記述を短くするには、繰り返しコマンドの中で置換などを直接実行せず、
置換コマンドを文字列として生成して、実行は繰り返しの外でコマンドコマンドでやるのが常用テクニックです。

24424 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? 悲しげ 2004/01/27-12:44
記事番号24422へのコメント
どもっ、うにんさん、

>だと処理が違います。(これは未定義でない項目値はそのままにしていますよ)
>置換 [貸室01午前行事]=#cond([貸室01午前行事],"予約済") \
>でしょう。

あ、そうでした。(^^;)(^^;)

>貸室が61になったりしたらシステムを全部作り直さないといけないので、
>普通はそういう風に(縦に)作るでしょうね。

やり方によって色々あるでしょうけど、例えば

貸室   曜日 午前行事 午後行事 夜間行事
−−−−+−−+−−−−+−−−−+−−−−
貸室01  月       予約済
・・・・・・・・・・・・・・・・・・・・・
貸室20  土            予約済

とか、目的に応じて。

24425 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? アックン(=^・^=) 2004/01/27-13:04
記事番号24409へのコメント
とまとさん、こんにちは。コマンドの実行タイムを表示する一括処理を一番下に載せておきます。
現状は、予約台帳,tblをいったん書き出して、それを週間使用詳細.tblに読み込んでから、
利用案内.tblに併合するという仕組みのようですね。

さて、佐田さんと悲しげさんが書かれている、速度低下の原因についてはこういうことです。
・繰り返しコマンドが速度低下の原因ではありません。
・置換コマンドと併合コマンドをたくさん発行していることが、速度低下の主な原因です。
わかりやすく説明すると・・・・・・。

a)
 置換 [貸室01午前行事]=""
  :
 置換 [貸室20夜間行事]=""
という書き方だと、置換コマンドが60回発行されます。

b)
 置換 [貸室01午前行事]="",・・・,[貸室20夜間行事]=""
という書き方だと、置換コマンド1回の発行で、60項目連続して置換します。
動作速度は、(b)の方が(a)よりかなり速くなります。

c)
 繰り返し &検索項目番号=1 , 60
   置換 ・・
 繰り返し終了
という書き方にすると、置換コマンドが60回発行されます。
この点で(a)と同じですから、(b)よりも遅くなります。
加えて繰り返しコマンドの分だけさらに遅くなるわけですが、
繰り返しコマンドで60回のループ動作にかかる時間は一瞬です。
一般に繰り返しのような実行制御系コマンドは非常に高速です。

なにはともあれ、実感して納得するほうが身に付くと思います。
下の・・・の箇所は適当に変えてください。
同じ項目を同じ計算式で置換すればいいです。

***------ タイム計測.cmd
表 "・・・.tbl"
var 時間{ &t1=#日時時刻( #日時値 ) }
for &秒=0 , 10000-1
  &秒 = &秒+1
end
確認  "繰り返し回数 / "+#str( &秒 )+"回: "+#str( #時間数値( #日時時刻( #日時値 )-&t1 , 3
) )+" 秒"
***------
var 時間{ &t1=#日時時刻( #日時値 ) }
置換 [・・・]=・・・ ,\
   [・・・]=・・・ ,\
    :
   [・・・]=・・・
確認  "置換コマンド1回: "+#str( #時間数値( #日時時刻( #日時値 )-&t1 , 3 ) )+" 秒"
***------
var 時間{ &t1=#日時時刻( #日時値 ) }
置換 [・・・]=・・・
置換 [・・・]=・・・
 :
置換 [・・・]=・・・
確認  "置換コマンド60回: "+#str( #時間数値( #日時時刻( #日時値 )-&t1 , 3 ) )+" 秒"
***------
24431 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? アックン(=^・^=) 2004/01/27-17:42
記事番号24422へのコメント
とまとさん>
(No.24422) うにんさん
>一括処理の記述を短くするには、繰り返しコマンドの中で置換などを直接実行せず、
>置換コマンドを文字列として生成して、実行は繰り返しの外でコマンドコマンドで
>やるのが常用テクニックです。

うにんさんがいいこと書いていたので、例をいくつか書いてみました。
人によっていろいろな書き方があります。こんなふうに書くんだなというのがおわかりになれば結構です。

なお、新規作成した表で試せるように、項目名を "A"〜"T" にしています。
( "A" は"貸室01午前行事"、"T" は "貸室20夜間行事" に該当します。)

***---------------------------
/* 例1:項目名を直接指定して置換します。置換 [貸室01午前行事]="" という書き方です。 */

 for &秒=#項目番号("A") , #項目番号("T")
   &STR = &STR+",["+#項目属性(&秒,1)+"]="""""
 end
 &STR = "置換 "+#sstr( &STR , 2 )
 コマンド &STR

/* &STR = "置換 "+#sstr( &STR , 2 ) というのは、&STRの先頭の余分な "," を削除し、先頭に"置換 "
を付加する処理です。 */
***---------------------------

/* 例2:例1との違いは、&STRの"," 削除と"置換 "付加をループ内で処理している点です。 */

 for &秒=#項目番号("A") , #項目番号("T")
   &STR = #cond( &秒=#項目番号("A") , "置換 "+"["+#項目属性(&秒,1)+"]=""""" ,\
          &秒=<#項目番号("T") , &STR+",["+#項目属性(&秒,1)+"]=""""" )
 end
 コマンド &STR
***---------------------------

/* 例3:項目名を直接書かないで、変数に代入した項目番号で置換します。とまとさんの「置換 &検索項目番号=""」と同じ書き方です。 4行目の "[" と "]" は、配列変数 $Cnt[] の [] 部分です。
項目名の[] ではありません。*/

var 整数{ &Cnt[60] }
 &STR = ""
 for &秒=#項目番号("A") , #項目番号("T")
   &STR = &STR+",&Cnt["+#str(#setvar("Cnt",&秒,&秒))+"]"+"="""""
 end
 &STR = "置換 "+#sstr( &STR , 2 )
 コマンド &STR
***---------------------------

/* 例4:例3との違いは、&STRの"," 削除と"置換 "付加をループ内で処理しています。 */

 var 整数{ &Cnt[60] }
 for &秒=#項目番号("A") , #項目番号("T")
   &STR = #cond( &秒=#項目番号("A") ,\
          "置換 "+"&Cnt["+#str(#setvar("Cnt",&秒,&秒))+"]"+"=""""" ,\
          &秒=<#項目番号("T") ,\
          &STR+",&Cnt["+#str(#setvar("Cnt",&秒,&秒))+"]"+"=""""" )
 end
 コマンド &STR
***---------------------------
なお、例1は動作テストしていません。
24443 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? とまと 2004/01/27-22:21
記事番号24409へのコメント
悲しげさん、佐田さん、うにんさん、アックンさん
ご親切なアドバイスをいただき大変ありがとうございます。

このアプリは私の勤務する職場というよりも、私の勤務する職場を含む職場群で昨年の4月から利用しております。

基本表である予約台帳.tblには、申込日付、貸室名、使用者、行事名、使用日付、使用時間帯(午前、
午後、夜間、午前・午後、午後・夜間、全日)、入金額、入金日付及びその他の必要事項を入力しています。

これを日次報告、月次報告、さらに週間利用予定、そして今回の投稿の素材である利用案内といった20種類近い
帳票の仕様に合わせるために、作業表(当日使用詳細、当月使用詳細、週間使用詳細)を利用しております。
これらの帳票はコンピュータ処理を前提に作られたものではなく、以前の手作業の頃から仕様で、
貸室の並びが縦のものもあれば横のものもあり、それに合わせる形で印刷対象表や作業表を作っております。
そういったことから、今回アドバイスをいただいた方々には奇異な印象を持たれたかもわかりません。

基本的には、予約台帳を月単位または週単位で絞り込んで、作業表に読み込み、そこで貸室・時間帯ごとの
利用件数や利用人数等に分類集計しております。この分類については作業表で#条件選択関数を利用した計算項目を設け、
入力項目をもとにして横に展開しております。
この作業表を直接、あるいは行集計等で編集して、印刷対象表に併合しております。

ところで、「置換や併合を繰り返すと処理速度が遅くなる」ということは、以前このBBSで目にした記憶があるのですが、
余りにも冗長なイベントの記述をすっきりさせたいという思いで、「繰り返し」コマンドを使って記述を修正しました。

しかし、このアプリのメンテを後継者に引き継がなければならないという事情もあり、
そのためには素人目に処理の流れがわかりやすい方がいいのかなとも思っております。
したがって、悲しげさんのご指摘どおりに、「繰り返し」コマンドは使わずに、「注2」「注3」は残し、
「注4」を改めることにします。「注4」の記述については、うにんさんのご指摘のとおりです。

今回、ご示唆いただいた「コマンド」コマンドは、これまでからこのBBSで目にしておりましたが、
難解なこともあってこれまで使用しておりません。これを契機に勉強してみたいと思います。

今後ともよろしくお願いいたします。

とまと

24445 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? うにん 2004/01/27-23:15
記事番号24443へのコメント

>今回、ご示唆いただいた「コマンド」コマンドは、これまでからこのBBSで目にしておりましたが、
>難解なこともあってこれまで使用しておりません。これを契機に勉強してみたいと思います。

確かに難解というか、処理の内容がわかりにくくなるし、固定した処理をわざわざ「コマンド」にすると処理速度は
むしろ(わずかでしょうが)遅くなるはずです。

同じような項目名を羅列するとコピーペーストした時に直し忘れて同じ項目を2回使ってしまったり、
というミスを防ぐのには役立つかも(?_^)

24446 Re:「繰り返し」コマンドを使うと処理時間が長くなるのでしょうか? とまと 2004/01/28-00:08
記事番号24445へのコメント
うにんさん

>確かに難解というか、処理の内容がわかりにくくなるし、固定した処理をわざわざ「コマンド」
>にすると処理速度はむしろ(わずかでしょうが)遅くなるはずです。
>
>同じような項目名を羅列するとコピーペーストした時に直し忘れて同じ項目を2回使ってしまったり、
>というミスを防ぐのには役立つかも(?_^)
>
重ね重ね親切なご指導ありがとうございます。

とまと
24449 「コマンド」コマンドは使わない方が無難です 佐田 守弘 2004/01/28-01:05
記事番号24443へのコメント
とまとさん
「コマンド」コマンドは、それを使わなければ処理できない様な特別の理由があるなら別ですが、
通常通りに記述できるのであれば、仮にそのために行数が増えたとしても、使わない方が無難です。

どうやらトマトさん自身が作って、その後の保守点検も全て引き受けるのではなく、
職場全体に普及させたい様ですから、「コマンド」コマンドを使っての記述はやめておきましょう。

●理由
記述しているコマンドを一目見て何をしているかが把握できない事に尽きます。
それ以外の理由はありません。しかしこれは大きな理由です。

・エラーがあってもデバッグしにくい
 (実行するコマンドの記述が入力されている変数値が正しいか、一目で解りません。
・他の人が訂正したり、応用する事が難しい。
 その様なアプリを作ってしまうと、地獄の果てまで保守責任を求められます。

●桐の一括処理は解りやすさが第一です
職場改善活動に「見える」改善などがありますね。「見える」という事がとても大切です。
多数の人を巻き込むには、「見える」事こそが大切です。
桐の一括処理も同じで、一目見て、何をしているのかがすぐに解る事が大切です。
解りやすい一括処理は、間違いも少ないでしょうし、デバッグも容易です。
また、職場に普及して、後継者を育成するにも大切です。

そのために、桐のコマンドは日本語記述が基本になっています。

●敢て解りにくく書く場合
しかし特定の理由があって、敢て解りにくく、理解できない様な作り方をする場合もあります。
・数行に書けば解りやすい式を無理に1行にまとめて記述する。
・実行するパラメータなどを変数で指定し、実際には何の値が代入されているかを解析しにくくする。
・実行コマンドを計算式で作り、「コマンド」コマンドで実行させる。
などなど。
これは、開発して納入したシステムの改ざんや転用を防ぐ目的があるある場合です。

佐田守弘(KS-00119)

戻る