Sign in Join
Wiki copytemporary

Avoiding implicit try finally section/id: what changed

Revision 1 to 2. 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-`Time of Foo_Normal: 141`\
47-`Time of Foo_Faster: 17`
46+```
47+Time of Foo_Normal: 141
48+Time of Foo_Faster: 17
49+```
4850
4951- 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).
5052
5153 {$mode objfpc}{$H+}
5254
5355 uses
5456 {BaseUnix, Unix hanya diperlukan untuk mengimplementasi Clock} BaseUnix, Unix,
5557 SysUtils;
5658
5759 function Clock: Int64;
5860 var Dummy: tms;
5961 begin
6062 Clock := FpTimes(Dummy);
6163 end;
6264
6365 procedure Foo_Normal(i: Integer);
6466 var S: string;
6567 begin
6668 if i = -1 then
6769 begin
6870 S := 'Some operation with AnsiString';
6971 raise Exception.Create(S);
7072 end;
7173 end;
7274
7375 procedure Foo_Faster(i: Integer);
7476
7577 procedure RaiseError;
7678 var S: string;
7779 begin
7880 S := 'Some operation with AnsiString';
7981 raise Exception.Create(S);
8082 end;
8183
8284 begin
8385 if i = -1 then RaiseError;
8486 end;
8587
8688 { Catatan bahwa ketika saya memanggil Foo_Normal dan Foo_ResourceString
8789 i selalu >= 0 maka Eksepsi tidak pernah dimunculkan.
8890 Maka konstan string SNormal dan SResString tidak benar-benar dipakai. }
8991
9092 const
9193 TestCount = 10000000;
9294 var
9395 i: Integer;
9496 Start: Int64;
9597 begin
9698 Start := Clock;
9799 for i := 0 to TestCount do Foo_Normal(i);
98100 Writeln('Time of Foo_Normal: ', Clock - Start);
99101
100102 Start := Clock;
101103 for i := 0 to TestCount do Foo_Faster(i);
102104 Writeln('Time of Foo_Faster: ', Clock - Start);
103105 end.
104106
105107---
106108*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