Sign in Join
Wiki copytemporary

Avoiding implicit try finally section/id: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Adakalanya berguna untuk mengetahui bahwa kompilator dapat melapisi beberapa kode dalam blok implisit try ... finally. Intinya ini diperlukan saat anda menggunakan variabel tipe apapun yang harus diinisialisasi / difinalisasi (misalnya prosedur standar Initialize() dan Finalize() melakukan sesuatu yang berarti dengannya), seperti AnsiString atau Variant atau array dinamis. Atau (hanya dalam FPC sebelum tertanggal 2004-12-26) resource string.
22
33Contohnya prosedur seperti
44
55 procedure P;
66 var S: AnsiString;
77 begin
88 ... do something with S ...
99 end;
1010
1111sebenarnya dikompilasi seperti
1212
1313 procedure P;
1414 var S: AnsiString;
1515 begin
1616 Initialize(S);
1717 try
1818 ... do something with S ...
1919 finally Finalize(S) end;
2020 end;
2121
2222Ini diperlukan, untuk memastikan jumlah referensi dari S yang akan dikurangi dengan benar saat prosedur P kan keluar dengan eksepsi. Tapi dalam beberapa kasus ini dapat mempengaruhi secara signifikan kecepatan atas kode yang diberikan.
2323
2424Ini adalah link ke diskusi yang diarsipkan pada daftar fpc-devel berkenaan dengan isu ini, dengan subyek "TList slowness in classes" : <http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg01367.html>
2525
2626Catatan bahwa ansistring temp vars dapat dibuat secara implisit. Cara yang paling nyata untuk memastikan apa yang terjadi padanya adalah membaca output asm.
2727
2828## Solusi yang Mungkin
2929
3030- BARU! gunakan {\$implicitexceptions off} Pastikan bahwa anda hanya menggunakan ini pada versi rilis dari program anda. Mendebug dapat menjadi masalah dengan sakalr terutama mencari kebocoran memori dan kerusakan.
3131
3232- pisahkan kode yang jarang digunakan yang menyebabkan implisit try finally ke dalam prosedur terpisah. (anda dapat menggunakan prosedure dalam procedure) (diverifikasi)
3333
3434- gunakan parameter const daripada parameter nilai. (hindari untuk mengubah refcount tapi temps masih dapat bermasalah).
3535
3636- gunakan global vars. (harus berhati-hati dengan masalah reentrency di sini dan temps masih dapat bermasalah).
3737
3838- gunakan non tipe refcounted seperti shortstrings.
3939
4040## Program Demo
4141
4242Dan di bawah ini adalah program demo kecil yang
4343
4444- Ketika dijalankan, dengan jelas memperlihatkan bahwa menghindari implisit blok try ... finally dapat menjadikan kode jauh lebih cepat. Ketika saya menjalan program ini pada sistem saya, Saya memperoleh
4545
46-```
46+```text
4747Time of Foo_Normal: 141
4848Time of Foo_Faster: 17
4949```
5050
5151- Memperlihatkan trik bagaimana untuk menghindari implisit blok try ... finally (tanpa mengubah arti atau keamanan kode) dalam beberapa kasus (ketika anda tidak memerlukannya gunakan AnsiString/Variant/something setiap kali procedure dipanggil tapi misalnya hanya jika beberapa parameter memiliki nilai tertentu).
5252
5353 {$mode objfpc}{$H+}
5454
5555 uses
5656 {BaseUnix, Unix hanya diperlukan untuk mengimplementasi Clock} BaseUnix, Unix,
5757 SysUtils;
5858
5959 function Clock: Int64;
6060 var Dummy: tms;
6161 begin
6262 Clock := FpTimes(Dummy);
6363 end;
6464
6565 procedure Foo_Normal(i: Integer);
6666 var S: string;
6767 begin
6868 if i = -1 then
6969 begin
7070 S := 'Some operation with AnsiString';
7171 raise Exception.Create(S);
7272 end;
7373 end;
7474
7575 procedure Foo_Faster(i: Integer);
7676
7777 procedure RaiseError;
7878 var S: string;
7979 begin
8080 S := 'Some operation with AnsiString';
8181 raise Exception.Create(S);
8282 end;
8383
8484 begin
8585 if i = -1 then RaiseError;
8686 end;
8787
8888 { Catatan bahwa ketika saya memanggil Foo_Normal dan Foo_ResourceString
8989 i selalu >= 0 maka Eksepsi tidak pernah dimunculkan.
9090 Maka konstan string SNormal dan SResString tidak benar-benar dipakai. }
9191
9292 const
9393 TestCount = 10000000;
9494 var
9595 i: Integer;
9696 Start: Int64;
9797 begin
9898 Start := Clock;
9999 for i := 0 to TestCount do Foo_Normal(i);
100100 Writeln('Time of Foo_Normal: ', Clock - Start);
101101
102102 Start := Clock;
103103 for i := 0 to TestCount do Foo_Faster(i);
104104 Writeln('Time of Foo_Faster: ', Clock - Start);
105105 end.
106106
107107---
108108*From the Free Pascal wiki, page "Avoiding implicit try finally section/id", as it stood on 2015-07-22 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history