こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VBでVC++の処理速さを実現する

ふと疑問に思ったので質問します。

あくまでも一般論ですが、VBはVC+より簡単だけどデメリットは処理速度が遅いことだそうです。

でもどちらも最終的には機械語?に訳されるんでしょ?

じゃあ人間にとって作りやすいVBで作っても、最終的にはコンパイラがVC++と同じ機械語にしてくれたら良いと思うのですが。

どうしてそういう都合の良いことは出来ないのですか?

投稿日時 - 2004-03-27 07:20:05

QNo.816084

暇なときに回答ください

質問者が選んだベストアンサー

なんかいろいろと話が出てますが。

本質的にVBとVC++の違いは

>あくまでも一般論ですが、VBはVC+より簡単だけどデメリットは処理速度が遅いことだそうです。

ですよね。

で、”簡単”というところでVBがどうして簡単なのかを考えていけばわかると思います。

簡単な理由:
1.データ型を意識しなくても自動的に変換してくれる
・・・VBが内部的にがんばって変換する処理を行っている

2.文字列が簡単に扱える。
・・・VBが内部的に、領域確保やメモリ内のデータのコピーなどの処理をがんばってる。

3.画面にコントロールを貼り付けるだけで、簡単にGUIが完成する。
・・・VBがフォームの表示等の一般的な必要となる処理、コントロールとのやり取りの処理等をすべて内部的に行っている。

4.ActiveXコンポーネントやCOMオブジェクトが簡単に使える。
・・・VBが内部的なコンポーネントとのインターフェイス間のやり取りをすべて行っている。

みたいな感じですかね?

ランタイムが必要とか、コンパイルが必要とかということとは別問題です。

ランタイムは、あくまでもVBのプログラムで内部的に共通で
行われる処理をまとめてDLL等にしたり、
VBで直接使用しづらい処理をActiveXコンポーネントにすとといったために使用します。

コンパイルも、ちゃんとネイティブコンパイルできますし。

で、このVBの簡単な点が全て実行速度というところに跳ね返ってきます。


2.やランタイムについては、VitaminBBさんはMFCをよく使われているのであれ?と思ったかもしれません。

MFCはCStringで簡単に文字列を扱えますし、MFCにはランタイムDLLも存在します。

実は、MFCもVBほどではないですが、”遅い”です。
フレームワークがC++で書かれているから速いとか言う問題ではなく、単純に、ある程度何でもできるフレームワークだから内部的な処理が多すぎるという点でMFCは遅いのです。

つまり、便利→内部的な処理が多い→遅いということになります。

#ただ、MFCの場合は、画面まわり、すなわちユーザーインターフェイスをMFCに任せ、演算などの高速処理を必要とするビジネスロジックはMFCを使わないということもできるので、このあたりがVBと違うところです。
VBで速くしようとすると、画面はVB、ビジネスロジックはCのDLLなんてことになります(よくありますが)。

投稿日時 - 2004-03-27 11:47:14

お礼

回答ありがとうございます。

投稿日時 - 2004-03-27 21:00:45

このQ&Aは役に立ちましたか?

11人が「このQ&Aが役に立った」と投票しています

回答(12)

ANo.12

>#いいのかなぁ、ここにツッコミ入れて・・・
>>Private Sub QuickSort(ByRef strData() As String, ByVal lngStartIndex As Long, ByVal lngEndIndex As Long)
>整数値ではなく文字列の配列に見えるんですが・・・

ご指摘ありがとうございます。間違って違うものを貼り付けてしまいました。
自宅のPCにはVBが入っていないんですけど、Access の VBA で作った文字列配列をソートする関数がありまして、これを会社の自分のメールアドレスにメールして、会社で休憩時間に String → Long に直してコンパイルして、できた Exe をまた自宅のPCにメールして、自宅のPCでテストしてみたんですけど、間違って、文字列ソート用の関数を貼り付けてしまいました。
こんなことやっていると信頼性がないと思うんですけど、一応、訂正しておきますと、
VBの関数は↓

Private Sub QuickSort(ByRef lngData() As Long, ByVal lngStartIndex As Long, ByVal lngEndIndex As Long)

でした。

投稿日時 - 2004-03-31 10:28:57

お礼

回答ありがとうございます。

ということはやはり20倍の差が有るって言うこと?
凄い。

投稿日時 - 2004-04-02 21:41:59

ANo.11

#いいのかなぁ、ここにツッコミ入れて・・・

>Private Sub QuickSort(ByRef strData() As String, ByVal lngStartIndex As Long, ByVal lngEndIndex As Long)

整数値ではなく文字列の配列に見えるんですが・・・

投稿日時 - 2004-03-31 00:53:11

お礼

回答ありがとうございます。

投稿日時 - 2004-04-02 21:40:45

すんません、、、開発ツールの事をいって回答になって無かったですね。

>>じゃあ人間にとって作りやすいVBで作っても、
>>最終的にはコンパイラがVC++と同じ機械語にしてくれたら良いと思うのですが。
確かにそう思った事が以前ありました。
でもそれは、昔アセンブリ言語で書いてた時の発想で
それが実現したのがC言語でもあるんです。
あえて言えば、「C#」が貴方の求めている開発ツールかもしれません
「C#」のねらいはVBの開発の容易さとC++の奥深い機能をあわせもつものなので。

なぜVBでランタイムを必要としないコンパイラーにしないかと言うと
VBの当初の目的は、BASIC言語同様「教育レベル」向けで、業務向けのツールではなかったのです。
VB2.0までが思惑通りの「教育向け」でしたが
VB3.0からにわかに業務利用され
VB4.0で当初の目的に合わなくなり
VB5.0で開発向けツールになりました
VB6.0で完全に開発ツールとなりました。
なので、当初からプロフェッショナル向けのVCがあるのでVBでネイティブに機械語に変換するコンパイルを作る事はないと思われます。

投稿日時 - 2004-03-31 00:03:58

お礼

回答ありがとうございます。

投稿日時 - 2004-04-02 21:40:18

最近マイクロソフト系で開発してないので度忘れしてますので嘘偽りがあるかもしれませんので空耳程度に、、。

VBとVC++またはC言語系MFCをマイクロソフトの
開発ソフトで行う場合。
コンパイル側では機械語に訳詞直すので、処理的には大差は無いです。(VBの変換の方が若干お馬鹿だった気はします)
ですがVBの場合のランタイムと言うライブラリーを返してコードの実行を行っていますのでその分遅くなり処理時間に差が出てきます。
また、VBでもVC++でも結局 MSのAPIを呼ぶ事が大半なので、VB側でも遠まわしにAPIを呼ぶランタイムを呼ぶのではなく、限りなく直接APIを呼んだ方が圧倒的に早くなります。

なのでVCとVBで実行速度を量るソースを作ったとしても、VB側でAPI呼び出しにランタイムを使っている段階2度デマを踏んでいるので、VCより早くなる事は無いです。

投稿日時 - 2004-03-30 23:33:41

お礼

回答ありがとうございます。

投稿日時 - 2004-04-02 21:38:58

ANo.8

ちょっと遅くなりました。
結論を先に言うと、私としては予想以上に差が出たという気がします。
要素数 10000 の 32 bit 整数配列のソート(クイックソート)を 1000 回繰り返したときの所要時間は
VC++ : 3 sec
VB : 61 sec
でした。( Pentium (3) 730MHz + Memory 384MB + WindowsXP )

ちなみにソースは
=== C ===
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void qsort( int *piData, int iStart, int iEnd );

int main( int iArgc, char *pstrArgv[] )
{
  if( iArgc < 2 ) {
    printf( "Usage : QuickSort FileName NumberOfData" );
    return( -1 );
  }

  FILE *fp = fopen( pstrArgv[1], "r" );
  if( NULL == fp ) {
    printf( "%s が見つかりません.\n", pstrArgv[1] );
    return( -1 );
  }

  int iNumberOfData;
  int *piData;
  int *piWork;
  char strBuffer[100];
  char *p;
  int i;
  time_t tStart;
  time_t tEnd;
  int iRepeat;

  iNumberOfData = atoi( pstrArgv[2] );
  iRepeat = atoi( pstrArgv[3] );
  piData = new int[iNumberOfData];
  i = 0;
  do {
    p = fgets( strBuffer, 100, fp );
    if( NULL != p ) {
      piData[ i ] = atoi( strBuffer );
      i++;
      if( iNumberOfData <= i ) {
        break;
      }
    }
  } while ( *p );
  fclose( fp );

  piWork = new int[iNumberOfData];
  tStart = time(NULL);
  for( i = 0; i < iRepeat; i++ ) {
    for( int j = 0; j < iNumberOfData; j++ ) {
      piWork[ j ] = piData[ j ];
    }
    qsort( piWork, 0, iNumberOfData - 1 );
  }
  tEnd = time(NULL);
  printf( "%d [s]\n", tEnd - tStart );

  fp = fopen( pstrArgv[3], "w" );
  if( NULL == fp ) {
    return( -1 );
  }
  for( i = 0; i < iNumberOfData; i++ ) {
    fprintf( fp, "%6d\n", piWork[ i ] );
  }
  fclose( fp );

  return( 0 );
}

void qsort( int *piData, int iStart, int iEnd )
{
  int iForward;
  int iBackward;
  int iTemp;

  if( iEnd <= iStart ) {
    return;
  }

  iForward = iStart + 1;
  iBackward = iEnd;

  while( iForward <= iBackward ) {
    while( iForward <= iBackward ) {
      if( piData[ iStart ] < piData[ iForward ] ) {
        break;
      }
      iForward++;
    }

    while( iForward <= iBackward ) {
      if( piData[ iBackward ] < piData[ iStart ] ) {
        break;
      }
      iBackward--;
    }

    if( iBackward <= iForward ) {
      break;
    }

    iTemp = piData[ iBackward ];
    piData[ iBackward ] = piData[ iForward ];
    piData[ iForward ] = iTemp;

    iForward++;
    iBackward--;
  }

  iTemp = piData[ iBackward ];
  piData[ iBackward ] = piData[ iStart ];
  piData[ iStart ] = iTemp;

  qsort( piData, iStart, iBackward - 1 );
  qsort( piData, iBackward + 1, iEnd );
}

=== VB ===
Private Sub Command1_Click()

  Dim iFileNo As Integer
  Dim lngData() As Long
  Dim lngWork() As Long
  Dim dtStart As Date
  Dim dtEnd As Date
  Dim i As Integer
  Dim iNumberOfData As Long
  Dim iRepeat As Integer
  Dim strCommand() As String

  strCommand = Split(Command(), ",")
  iNumberOfData = CInt(strCommand(0))
  iRepeat = CInt(strCommand(2))

  iFileNo = FreeFile
  Open strCommand(1) For Input Access Read As #iFileNo
  ReDim lngData(iNumberOfData)
  For i = 0 To iNumberOfData - 1
    Input #iFileNo, lngData(i)
  Next i
  Close #iFileNo

  dtStart = Now
  For i = 1 To iRepeat
    lngWork = lngData
    QuickSort lngWork, 0, 9999
  Next i
  dtEnd = Now
  MsgBox DateDiff("s", dtStart, dtEnd), vbInformation

End Sub

Private Sub QuickSort(ByRef strData() As String, ByVal lngStartIndex As Long, ByVal lngEndIndex As Long)
  Dim strWork As String
  Dim i As Long
  Dim j As Long

  If lngStartIndex >= lngEndIndex Then Exit Sub

  i = lngStartIndex + 1
  j = lngEndIndex
  Do While i <= j
    Do While i <= j
      If strData(i) > strData(lngStartIndex) Then
        Exit Do
      End If
      i = i + 1
    Loop
    Do While i <= j
      If strData(j) < strData(lngStartIndex) Then
        Exit Do
      End If
      j = j - 1
    Loop

    If i >= j Then Exit Do

    strWork = strData(j)
    strData(j) = strData(i)
    strData(i) = strWork

    i = i + 1
    j = j - 1
  Loop

  strWork = strData(j)
  strData(j) = strData(lngStartIndex)
  strData(lngStartIndex) = strWork

  Call QuickSort(strData, lngStartIndex, j - 1)
  Call QuickSort(strData, j + 1, lngEndIndex)
End Sub

という感じです。

投稿日時 - 2004-03-30 22:54:44

お礼

回答ありがとうございます。

凄い差ですね。

投稿日時 - 2004-04-02 21:37:31

ANo.7

結論書くの忘れてました(^^;

>どうしてそういう都合の良いことは出来ないのですか?

結論は無理。
理由は、同じ機械語でも、VBで書いた処理+VBの内部処理という2種類の処理を行うことになるからです。

単純な処理でもですね。
VBだと
Dim i As Integer
i = i + 1

Cだと
short i;
i = i + 1;

という式があった場合、Cでは単純に1加算しているだけですが、
これだけの式でもVBでは内部的に範囲チェックなどの処理が行われます。
i = 32767だった場合、符号付16ビット整数なのでさらに加算するとオーバーフローを起こします。

Cですと、何事もなく処理が続きますが、VBですと、オーバーフローのエラーが発生します。

VBは簡単でもあるし、安全でもあるということになりますが、このようなチェックは、やはり処理スピード的にはオーバーヘッドとなります。

投稿日時 - 2004-03-27 17:40:10

お礼

回答ありがとうございます。

大変良く分かりました。
要は、プログラマーが容易にコードが書けるようになっている分、背後で最適でない余分な処理も行われており、結果的には処理速度等の性能差が出ざるを得ないということですね。

大変良く分かりました。

投稿日時 - 2004-03-27 21:08:56

ANo.5

Pコードは、確かインタプリタ形式(実行時に機械語に変換して実行)だったと思います。

>趣味でプログラムしている人のレベルでは、
>単に、俺ってちょっと難しい言語でプログラムしてんだぜ。
>とか、プロが使うソフトを使ってるんだぜ。
>と自慢できるくらいでメリットは無いということなの?

そんなことはないです。VB でも API を使用すればたいていのことはできますが、VB ではできないこともあります。あるいは、VB ではできなくはないが、C/C++ の方がやりやすい(スマートに記述できる)ということもあります。具体的には、いろいろあると思いますけど、例えば、バイナリデータの取り扱いとか。
あと、VB でもクラスが使用できますが、VB のクラスは C++ のクラスのようにちゃんとしたものではない ( クラスの継承ができないなど ) ので、正統的なオブジェクト志向の設計をするなら VC にせざるを得ないということもあると思います。
まぁ、簡単に言うと「何でもできる度」は VC の方が上ということです。

実行速度については、ちょっと興味があるので、月曜日にでも試してみようと思います。(今、VB の開発環境が手元にないので。)
32bit 整数データのソート( Quick Sort ) を、同じデータをファイルから読み込ませて、ファイルの読み込みや出力を除いたソート実行部分の実行時間がどれくらいになるのか VB と VC で試してみようと思います。
(それまで締め切らないで待ってね。)

投稿日時 - 2004-03-27 11:45:35

お礼

回答ありがとうございます。

>(それまで締め切らないで待ってね。)

お言葉に甘えてお待ちしております。

投稿日時 - 2004-03-27 21:00:18

ANo.4

VB->ソースプログラム-コンパイラで処理->機械語
VC++->ソースプログラム-コンパイラで処理->機械語
で、観念的には、最終の機械語を実行すると言う(インタプリタ方式に対し)スピード面のメリットは同じですが、
VBを機械語にブレークダウンするロジックはVBにお任せであり、VC++は、より機械語に近い位置にあり、コーディングする人が熟達した人なら、より無駄のない早い(プログラムステップ数が少ない)コードが書けると言うことです。
なんでも出きるように考えた汎用品と機能を特化した注文品の例と一脈通ずるものがあると思います。
実際のプログラムでは、「どのような機械語群に直すか」が解決すべき問題です。
コンパイラでは、一般的にはコード上でどこが無駄が出やすいか判っており、オプチマイズや最適化とか言われる努力がコンパイラ側で工夫されており、この点の解決がコンパイラが出来て以来の最大の課題です。上記で「熟達した人なら」と書きましたが、下手なプログラマが書くと、無駄が多くて、コンパイラに負けるコードしか組めない場合もあり得るわけです。
(VC++もVBと同じコンパイラですが、VC++はより機械語に近いと言う意味で、コンパイラ-機械語と対比した機械語の方に入れて説明して見ました。VC++もコンパイラとしての同じ問題を抱えていますので程度問題ですが。)
コンパイラは全世界の優秀者、過去から今までの頭脳の知恵が結集された面があり、そう馬鹿にしたものではないのです。機械語の実行速度が飛躍的に上がり(昔の超大型コンピュタを今のパソコンが越える時代)、機械語実行時の無駄より、習得の易しいVBなどの言語を使って(一例ではVBなどはポインタなど意識させない)、ソースコードが早く、誤りが少なく完成するメリットの方が大きい時代になってます。
>「ふと疑問に思ったので」と書いておられるように
本質問は観念的な質問で、コンパイラに関する本を読んで
ソースからどういうロジックで機械語に翻訳するか(むしろせざるを得ないか)、そこにどういう無駄が発生し勝ちか、どういう改善策のパターンがあり、それ講じられているかを調べてください。

投稿日時 - 2004-03-27 08:37:19

お礼

回答ありがとうございます。

投稿日時 - 2004-03-27 20:58:53

ANo.3

BASICの特徴は書かれたソースコードを実行の都度
マシン語に翻訳している為に、速度が遅いことは免れません。

>>最終的にはコンパイラがVC++と同じ機械語にしてくれたら良いと思うのですが。
VBは#1の方の説明がありますが、コンパイルを実行しないと
上述の実行時翻訳をしているのです。

Cと同じ位に速度を求めるならコンパイルをしなければ
早くなりません。

投稿日時 - 2004-03-27 08:37:12

お礼

回答ありがとうございます。

投稿日時 - 2004-03-27 20:58:03

ANo.2

> どうしてそういう都合の良いことは出来ないのですか?
ランタイムライブラリがないと動作しない設計 (仕様) だからです。
ランタイムライブラリや各種コンポーネントはソフトウェア開発者の利便性 (高生産性、ソフトウェア部品の再利用性) のために提供されているものです。
つまり、利便性と実行ファイルのパフォーマンス (処理速度、ファイルサイズのコンパクトさ) はトレードオフ関係にあります。

無論、VC++でも各種コンポーネント (MFC等?) を使うことは可能です。
というより、生産性を考えると、コンポーネントを一切使用しないでソフトウェアを作るのは現実的ではないでしょう。
こうしたコンポーネントを使用すると、VC++ / VB の速度差は少なくなるものと思われます。
例えば、ADOを介してSQL Serverに接続し、データベースを操作する、といったアプリケーションでは、処理の大半はミドルウェアとDBが実行することになるため、フロントエンドのアプリケーションがVC++ / VB (またはDelphi) のいずれであっても性能に大差はないでしょう。

もう一点、VBのパフォーマンス上のボトルネックで無視できないのは文字列の処理です。
VBの文字列連結演算子は内部的にはメモリ領域を動的に確保する動作となるため、多用すると必然的に処理速度が遅くなります。
(他の文字列処理についても同様?)
これを回避するには、文字列連結演算子を極力使用しない、Byte型の配列を使用する、といった工夫が必要になります。
しかし、コーディングの容易さ、可読性という観点からみると、RADツールを使用する利点が失われる、とも言えます。

※ 現実の社会ではソフトウェアの処理速度が遅い原因の90%以上は、プログラミングツールではなく、能力の開発者の能力にあります。
(VBの性能を云々する人ほど効率、品質の悪いコードを書く傾向が強い)

以上、どシロウトの意見でした。
(専門家のフォローを希望します)

投稿日時 - 2004-03-27 07:52:33

お礼

回答ありがとうございます。

そうですね。速度差もあえて上げればというくらいで、そう大差ないのですね。

そうすると、VC++のメリットってなんなのでしょうか?

趣味でプログラムしている人のレベルでは、
単に、俺ってちょっと難しい言語でプログラムしてんだぜ。とか、プロが使うソフトを使ってるんだぜ。と自慢できるくらいでメリットは無いということなの?

投稿日時 - 2004-03-27 08:17:33

ANo.1

VBにもネイティブコードとPコードってのがあって、
ネイティブコードだったら、VCと遜色ないくらい
早いですよ。
当然、マシン語ですけども。

また、VCのメリットは、1つのプログラムで2つの処理を同時にできることです。
VBはできません。

投稿日時 - 2004-03-27 07:42:52

お礼

回答ありがとうございます。

Pコード、ネイティブコードってなんですか?

投稿日時 - 2004-03-27 08:11:54

あなたにオススメの質問