Java, Delphi, C++Builderユーザのためのメモリリーク, ボトルネックの検出手順

Similar documents
1 シミュレーションとは何か?

7th CodeGear Developer Camp

PowerPoint Presentation

CodeGear Developer Camp

21st Embarcadero Developer Camp

Microsoft PowerPoint - はじめてのDataSnapアプリケーション_

開発者が知りたい実践プログラミングテクニック!

25th Developer Camp

Thread

「RAD Studio XE5によるマルチ言語/マルチデバイス開発の進め方」

1 Java Java GUI , 2 2 jlabel1 jlabel2 jlabel3 jtextfield1 jtextfield2 jtextfield3 jbutton1 jtextfield1 jtextfield2 jtextfield3

知って得する!現役ヘルプデスクが答えるDelphiテクニカルエッセンス 9.0

WebReportCafe

Javaセキュアコーディングセミナー東京 第3回 入出力(File, Stream)と例外時の動作 演習解説

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

新・明解Java入門

24th Embarcadero Developer Camp

Microsoft PowerPoint - visualprogram.ppt

ガイダンス

ガイダンス

2016 年度 JAVA 講座第六週目 目次 パッケージ... 2 パッケージの作成... 2 パッケージの使用方法... 3 異なるパッケージ同名クラスの宣言... 4 パッケージの側面から見たアクセス修飾子... 4 ラッパークラス... 5 ラッパークラス利用法:キャスト... 5 ラッパーク

Embarcadero Developer Camp

Prog2_9th

ガイダンス

Prog1_10th

オブジェクト指向プログラミング・同演習 5月21日演習課題

. IDE JIVE[1][] Eclipse Java ( 1) Java Platform Debugger Architecture [5] 3. Eclipse GUI JIVE 3.1 Eclipse ( ) 1 JIVE Java [3] IDE c 016 Information Pr

21st Embarcadero Developer Camp T8

ガイダンス

Developer Camp

Java演習(4) -- 変数と型 --

14th Developer Camp

AquesTalk プログラミングガイド

Java言語 第1回

メソッドのまとめ

Microsoft PowerPoint ppt

AquesTalk Win Manual

ガイダンス

Microsoft PowerPoint - prog09.ppt

Microsoft PowerPoint - DELPHI�礔.ppt

Microsoft PowerPoint - prog09.ppt

HashMapからConcurrentHashMapへの移行

目 次 Java GUI 3 1 概要 クラス構成 ソースコード例 課題...7 i

<リスト1> AD コンバータへのデータの出力例 NEC PC98 用 mov al,22h // CLK -> 1, CS -> 0, DI -> 0 out 32h,al // シリアル ポートにデータ出力 PC/AT 互換機用 mov al,00h // CLK -> 1 mov dx,3fb

JavaプログラミングⅠ

Java知識テスト問題

NetworkVantage 9

JAVA とテンプレート

Microsoft PowerPoint - OOP.pptx

ファイル操作

About me! 足立昌彦 / +Masahiko.Adachi )! バイドゥ株式会社技術顧問 (Simeji)! 株式会社カブク Co-Founder! Google Developer Expert (Android)

「DataSnapユースケース研究」 多層技術の概要と最適化、実践テクニック

7th CodeGear Developer Camp

Developer Camp

やさしいJavaプログラミング -Great Ideas for Java Programming サンプルPDF

10/31 Java AWTの基本構造(Frameクラスの継承) 演習課題資料

Java (9) 1 Lesson Java System.out.println() 1 Java API 1 Java Java 1

データ構造とアルゴリズム論

10th Developer Camp - B5

< F2D B838A835882CC8CF68EAE2E6A7464>

Programming-C-9.key

CashDrawer ライブラリ API 仕様書 2014/07/09 CashDrawer ライブラリ API 仕様書 Rev / 10

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

開発者が知りたい実践プログラミングテクニック! ~明日から使えるテクニック集~

データアダプタ概要

JEB Plugin 開発チュートリアル 第4回

28th Embarcadero Developer Camp

テクニカルセミナーベストセレクション

TestDesign for Web

第1章 ビジュアルプログラミング入門

Java - Visual Editor

第2回講義

Java プログラミング Ⅰ 3 回目変 数 今日の講義講義で学ぶ内容 変数とは 変数の使い方 キーボード入力の仕方 変 数 変 数 一時的に値を記憶させておく機能 変数は 型 ( データ型 ) と識別子をもちます 2 型 ( データ型 ) 変数に記憶する値の種類変数の型は 記憶できる値の種類と範囲

8th CodeGear Developer Camp

8th CodeGear Developer Camp

D:\Documents\Visual Studio 2015\Projects\MyHomePage 用サンプル \ExcelAndWord\ExcelAndWord\MainForm.cs 1 /* */ Excel や Word とやりとりする ~9,20 仕様 Excel

PowerPoint プレゼンテーション

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

Microsoft PowerPoint - prog13.ppt

Animals サンプル Step3 張り付けた動物の上をクリックすると それぞれの鳴き声で鳴く その鳴く間 一定時間 ( ここでは 1 秒間 ) 画像が別のものに変わる <アニメーションの基礎 : タイマーについて> アニメーションは アプリケーションが指定する間 一定間隔でどんどん画像をおきかえ

解きながら学ぶJava入門編

Exam : 1z1-809-JPN Title : Java SE 8 Programmer II Vendor : Oracle Version : DEMO Get Latest & Valid 1z1-809-JPN Exam's Question and Answers 1 from Ac

問題1 以下に示すプログラムは、次の処理をするプログラムである

< F2D834F838C A815B A CC>

GUI プログラミング第 4 Graph ~ 手書認識と関数グラフ描画 ~ マウスで数式を書いて認識し 関数グラフを描画する < 手書認識とグラフ描画のステップ> ステップ 1_1 フレームの作成 ステップ 1_2 マウスで自由に線を書く ステップ 2-1 手書認識認識結果を標準出力する ステップ

問 次の Fortran プログラムの説明及びプログラムを読んで、設問に答えよ。

Visual Studio2008 C# で JAN13 バーコードイメージを作成 xbase 言語をご利用の現場でバーコードの出力が必要なことが多々あります xbase 言語製品によっては 標準でバーコード描画機能が付加されているものもあるようで す C# では バーコードフォントを利用したりバー

< F2D F B834E2E6A7464>

B Simon (Trump ) SimonU.pas SimonP.dpr Name FormSimon Caption Position podesktopcenter uses Windows, Messages, SysUtils,

GUIプログラムⅣ

WebOTXプロファイラを使用したメモリリーク調査方法

awt の主要なクラスを下記に示す クラス Component Container Button Label Panel Frame 説明画面にユーザインターフェイス要素として表示し, ユーザとのやり取りを行うコンポーネントを表すすべてのコンポーネントのスーパークラスになる ほかのコンポーネントを含

< F2D8EA CE909482CC92EA82852E6A7464>

IT プロジェクト

Prog2_12th

21st Embarcadero Developer Camp T9

10/ / /30 3. ( ) 11/ 6 4. UNIX + C socket 11/13 5. ( ) C 11/20 6. http, CGI Perl 11/27 7. ( ) Perl 12/ 4 8. Windows Winsock 12/11 9. JAV

アジェンダ 1 グラフィカルなインタフェース GUI(Graphical User Interface) の基礎 2 Swing を利用する Swing の基礎知識 2

JavaプログラミングⅠ

AquesTalk Mac マニュアル

Transcription:

チュートリアルセッション #2 Java, Delphi, C++Builder ユーザのためのメモリリーク, ボトルネックの検出手順 講師紹介 高橋智宏 1973 年生まれ 京都大学法学部卒 エバンジェリスト兼コンサルタント兼トレーナー 学生の時購入したTurboC++2ndからの熱狂的なボーランドファン 参加しているメーリングリストやコミュニティ JBuilder ML,C++Builder ML,Delphi ML,C# ML,CORBA ML 等 ミクシィ http://mixi.jp/show_friend.pl?id=208738 Java 読書会 を運営 http://www.javareading.com/bof/

アジェンダ Java のメモリリークの落とし穴 OptimizeIt Profiler for Java C++Builder6,C++Builder2006 のメモリリークの落とし穴 CodeGuard Delphi for Win32 のメモリリークの検出方法 MemCheck, FastMM(BDS2006), 本家 FastMM Delphi for.net のメモリリークの落とし穴 OptimzieIt Profiler for.net1.1 CPU プロファイリング手順 Java, C++Builder, Delphi for Win32, Delphi for.net Delphi7 と BDS2006 でメモリマネージャの比較 Java のメモリリークの落とし穴 基本的に Java にはメモリリークが無いハズ public class Frame1 extends JFrame { JButton jbutton1 = new JButton(); public Frame1() {... jbinit(); private void jbinit() throws Exception {... jbutton1.settext(" フレームを表示 "); jbutton1.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { jbutton1_actionperformed(e); ); // フレーム (test.frame2) を表示 public void jbutton1_actionperformed(actionevent e) { test.frame2 f = new test.frame2(); // Frame2を生成 f.setvisible(true); // Frame2を表示 public class Frame2 extends JFrame { JButton jbutton1 = new JButton(); public Frame2() {... jbinit(); private void jbinit() throws Exception {... jbutton1.settext(" 閉じる "); jbutton1.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { jbutton1_actionperformed(e); ); public void jbutton1_actionperformed(actionevent e) { setvisible(false); // Frame2( 自分自身 ) を閉じる

OptimizeIt Profiler for Java で監視してみる 何故か test.frame2 を含む様々なインスタンスがガベコレされない メモリプロファイラで見るとインスタンス数が増えたまま test.frame2 インスタンスは確かに参照されている 自分のコード ( イベントハンドラ ) が参照しているのは当たり前だが 参照ツリーを使って 参照されている様子を確認 ネイティブピアからの参照が残らないよう dispose() または JFrame.DISPOSE_ON_CLOSE オプションが必要

C++Builder 特有の落とし穴 try/ finally でメモリリークを防ぐ class MyClass { ; void fastcall TForm1::Button1Click(TObject *Sender) { MyClass* p = NULL; try { p = new MyClass(); try { int x = StrToInt("xyz"); catch(const Exception& ex) { return; catch(...) { return; finally { if(p) { delete p; // 解放!! VCL インスタンスのリーク void fastcall TForm1::Button2Click(TObject *Sender) { new TButton((TComponent*)NULL); // Owner 無し!! C++Builder6 の CodeGuard で確認してみる C++Builder6 では なぜか finally が呼び出されない ( 仕様?) TButton インスタンスのリークは見つけられない ( 仕様?) MyClass オブジェクトが削除されていないと報告されました オススメは std::auto_prt boost::scoped_ptr

C++Builder2006 では? catch の中から return しても finally が呼び出されるようになりました VCL のインスタンスのリークも報告されるようになりました 但し 動的 RTL(cc3270xx.dll) とパッケージ (xxxx.bpl) は OFF にする CodeGuard のログファイルに ソースコードと行番号が出力されています C++Builder と catch() 例外の補足に catch() のみを使用するのってどう? VCL 例外に関連するメモリがリークするので注意!! ( バグ?) C++Builder2006 の CodeGuard でチェックしてみよう 誤 try { int x = StrToInt("xyz"); catch(...) { ShowMessage( ); 正 try { int x = StrToInt("xyz"); catch(const Exception& ex) { ShowMessage( ); catch(...) { ShowMessage( );

Delphi5~Delphi2005(Win32) - MemCheck Delphi2005 までは MemCheck がオススメ http://v.mahon.free.fr/pro/freeware/memcheck/ 無料 (MemCheck.pas のみ ) Delphi2006 では利用不可!! Delphi コンパイラやメモリマネージャの変更による影響の為 Delphi5~Delphi2005(Win32) MemCheck ( 続き ) MemCheck.pas をプロジェクトに追加 MemChk; の呼び出しを追加 スタックフレームの生成 を ON TD32 デバッグ情報を含める を ON プログラム終了時にログファイルが生成される MemChk; // チェック開始 Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. type TMyClass = class procedure TForm1.Button1Click(Sender: TObject); var p: TMyClass; p := TMyClass.Create; // 破棄されていない

Delphi2006 for Win32 FastMM BDS2006 から メモリマネージャが FastMM ベースに置き換わった BDN の記事 http://bdn.borland.com/article/33624 今までより高速 後ほど確認します メモリリーク報告機能が付属している ReportMemoryLeaksOnShutdown := True; の行を追加するだけ プログラム終了時にダイアログボックスが表示される しかし インスタンスの生成場所までは教えてくれない! ReportMemoryLeaksOnShutdown := True; // これだけ Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. Delphi2006 with 本家 FastMM リークしたインスタンスの生成場所は 実は Delphi2006 でも調べることができる!! BDS2006 付属の FastMM を 本家 FastMM の最新版に置き換えよう http://sourceforge.net/project/showfiles.php?group_id=130631 ライセンスは MPL 最新版は 4.70 ( ) ( )Delphi2006 以前のバーションでも利用可能

Delphi2006 with 本家 FastMM ( 続き ) uses に ShareMem ユニットを追加して borlndmm.dll( 共用メモリマネージャ ) がロードされるように変更する 本家 FastMM の Debug 版 BorlndMM.dll がロードされるようにする 本家 FastMM の FastMM_FullDebugMode.dll が実行時に必要 スタックフレームの生成 を ON TD32 デバッグ情報を含める を ON BDS2006 の IDE が起動している必要あり プログラム終了時にダイアログボックスが表示される プログラム終了時にログファイルが生成される borlndmm_memorymanager_eventlog.txt プログラムは最終的に AV で停止することがあるが 気にせず タスクマネージャや IDE 上で無理矢理終了させる Delphi2006 with 本家 FastMM ( 続き ) program XXXX; uses ShareMem, // これだけ Forms, Unit1 in 'Unit1.pas' {Form1, Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. --- borlndmm_memorymanager_eventlog.txt ---------------------- A memory block has been leaked. The size is: 4 Stack trace of when this block was allocated (return addresses): 402C9A [System][@GetMem] 40383B [System][TObject.NewInstance] 403BAA [System][@ClassCreate] 403870 [System][TObject.Create] 403A33 [System][@IsClass] 453693 [Unit1.pas][Unit1][TForm1.Button1Click][34] 437052 [Controls][TControl.Click] 426537 [StdCtrls][TButton.Click] 426635 [StdCtrls][TButton.CNCommand] The block is currently used for an object of class: TMyClass

Delphi for.net 特有の落とし穴 基本的に.NET にはメモリリークが無いハズ unit Unit1; type TForm1 = class(tform) Button1: TButton; procedure Button1Click(Sender: TObject); implementation uses Unit2; procedure TForm1.Button1Click(Sender: TObject); var f: TForm2; f := TForm2.Create(nil); // TForm2を生成 (Ownerはnil) f.showmodal; // TForm2を表示 unit Unit2; type TForm2 = class(tform) Button1: TButton; procedure Button1Click(Sender: TObject); implementation procedure TForm2.Button1Click(Sender: TObject); Close; // TForm2( 自分自身 ) を閉じる end. OptimizeIt Profiler for.net1.1( ) で監視してみる 何故か Unit2.TForm2 等のインスタンスがガベコレされない Owner が nil でも デフォルトの Owner がいるので x.free; または FreeAndNil(x); の呼び出しは必須 ( ) 単体販売は終了しています Delphi2005 Architect 版にのみライセンスが付属しています

CPU プロファイリング -Java public class Frame1 extends JFrame { JButton jbutton1 = new JButton(); public Frame1() { jbinit(); private void jbinit() throws Exception { jbutton1.settext("jbutton1"); jbutton1.addactionlistener(new Frame1_jButton1_actionAdapter(this)); contentpane.add(jbutton1, java.awt.borderlayout.south); public void jbutton1_actionperformed(actionevent e) { long st = System.currentTimeMillis(); long et = st; while( (et-st) < 5000 ) { Integer.parseInt("123"); et = System.currentTimeMillis(); JOptionPane.showMessageDialog(this, " 終わりました "); 5 秒間のループ処理 OptimizeIt Profiler for Java による CPU プロファイリング デフォルトは 5 ミリ秒間隔のサンプリングを実施

CPU プロファイリング C++Builder void fastcall TForm1::Button1Click(TObject *Sender) { unsigned long s = GetTickCount(); unsigned long e = s; while( (e-s) < 5000 ) { char buf[4]; sprintf(buf, "%s", "123"); e = GetTickCount(); ShowMessage(" 終わりました "); 5 秒間のループ処理 CPU プロファイリング C++Builder ( 続き ) LTProf の紹介 Lightweight Technologies 社の製品 http://www.lw-tech.com/ C++Builder/Delphi に対応した CPU プロファイラ 価格は $49.95(USD) TD32 デバッグ情報だけで OK

LTProf による CPU プロファイリング デフォルトは 3 ミリ秒間隔のサンプリングを実施 処理時間が長いメソッドが赤くハイライトされています CPU プロファイリング Delphi for Win32 procedure TForm1.Button1Click(Sender: TObject); var s,e: Cardinal; i: Integer; s := GetTickCount; e := s; while (e-s) < 5000 do i := StrToInt('123'); e := GetTickCount; ShowMessage(' 終わりました '); 5 秒間のループ処理

LTProf による CPU プロファイリング TD32 デバッグ情報を含める を ON デバッグ版 DCU を使う を ON 処理時間が長いメソッドが赤くハイライトされています CPU プロファイリング Delphi for.net procedure TForm1.Button1Click(Sender: TObject); var s,e: Cardinal; i: Integer; s := GetTickCount; e := s; while (e-s) < 5000 do i := StrToInt('123'); e := GetTickCount; ShowMessage(' 終わりました '); 5 秒間のループ処理

OptimizeIt Profiler for.net1.1 による CPU プロファイリング デフォルトは 5 ミリ秒間隔のサンプリングを実施 意外にも (?) GetTickCount 関数 (Win32API) の呼び出しがボトルネックに 処理時間の長い行がハイライトされています Delphi7 と BDS2006 でメモリマネージャの比較 Delphi7 は 従来のメモリマネージャを使用 BDS2006 は 製品に付属する FastMM ベースのものを使用 procedure TForm1.Button1Click(Sender: TObject); var i,j: Integer; s,e: Cardinal; list: TStringList; s := GetTickCount; for i := 1 to 100 do list := TStringList.Create; for j := 1 to 10000 do list.add(inttostr(j)); FreeAndNil(list); e := GetTickCount; Label1.Caption := IntToStr(e-s); TStringList を使った重いループ処理

Delphi7 だと 大量の TStringList.Add に伴うメモリの再配置処理 (ReallocMem,Move) が最も重く IntToStr メソッド (Sysutils::CvtInt) がその次に重い BDS2006 だと メモリの再配置処理は軽くなり 逆に IntToStr(Sysutils::CvtInt) が目立つ結果に Sysutils::CvtInt の実装内容は Delphi7 と BDS2006 とで同一です

Q&A