Delphi RegEx

Menyambung soal frekuensi kata kemaren, kali ini saya membandingkan RegEx di Delphi, Perl, PHP, dan Python. Delphi dan PHP menggunakan PCRE. Fasilitas hashing sesuai yang ada di masing-masing bahasa dan dianggap sudah optimal. Hasilnya sebagai berikut:

  1. Perl: 0,375s
  2. Delphi: 0,468s
  3. Python: 0,468s
  4. PHP: 1,125s

Tidak perlu disimpulkan apa-apa lah. Barangkali kalo ada yang mau nambahin
versi bahasa lainnya silakan saja. Btw, jumlah seluruh kata: 126944, jumlah kata unik: 11793.

Delphi:

program fkata2;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, PerlRegEx in 'PCRE\PerlRegEx.pas';

type
  TStringListZ = class(TStringList)
  protected
    function CompareStrings(const S1, S2: string): Integer; override;
  end;

function TStringListZ.CompareStrings(const S1, S2: string): Integer;
begin
  if CaseSensitive then Result := CompareStr(S1, S2)
  else Result := CompareText(S1, S2);
end;

var
  F: Text;
  S, SS: string;
  I, JumStr: Integer;
  TS: TStringList;
  Rdx, Rgx: TPerlRegEx;
begin
  JumStr := 0;
  TS := TStringListZ.Create;
  TS.Sorted := True;
  TS.Duplicates := dupIgnore;
  TS.CaseSensitive := False;
  Rgx := TPerlRegEx.Create(nil);
  Rgx.RegEx := '\b([a-zA-Z]+)\b';
  Rdx := TPerlRegEx.Create(nil);
  Rdx.Options := [preSingleLine];
  Rdx.RegEx := '<(TITLE|TEXT)>(.+)<\/\1>';
  AssignFile(F, 'Koleksi.dat');
  Reset(F);
  while not EoF(F) do begin
    Readln(F, S);
    SS := SS + S + ' ';
    if (S = '</DOC>') then begin
      Rdx.Subject := SS;
      if Rdx.Match then repeat
        Rgx.Subject := Rdx.SubExpressions[2];
        if Rgx.Match then repeat
          I := TS.Add(Rgx.SubExpressions[1]);
          TS.Objects[I] := TObject(Integer(TS.Objects[I]) + 1);
          Inc(JumStr);
        until not Rgx.MatchAgain;
      until not Rdx.MatchAgain;
      SS := '';
    end;
  end;
  Writeln('Jumlah seluruh kata: ', JumStr);
  Writeln('Jumlah kata unik: ', TS.Count);
end.

Perl:

open(FH, "Koleksi.dat") or die("Koleksi.dat: $!");
$/ = "</DOC>\n";
while (<FH>) {
  while (m/<(TITLE|TEXT)>(.+)<\/\1>/gcs) {
    $str = lc $2;
    while ($str =~ m/\b([a-z]+)\b/gcs) {
      $arr_kata{$1}++;
      $jum_kata++;
    }
  }
}
print "Jumlah seluruh kata: $jum_kata\n";
print "Jumlah kata unik: ", scalar keys %arr_kata, "\n";

PHP:

$fd = fopen("Koleksi.dat", "rt");
while ($s = fgets($fd)) {
  $str .= $s;
  if ($s == "</DOC>\n") {
    if (preg_match_all('/<(TITLE|TEXT)>(.+)<\/\1>/s', $str, $res)) {
      foreach ($res[2] as $text)
        if (preg_match_all('/\b([a-z]+)\b/s', strtolower($text), $res)) {
          foreach ($res[1] as $kata) {
            $arr_kata[$kata]++;
            $jum_kata++;
          }
        }
    }
    $str = "";
  }
}
print "Jumlah seluruh kata: $jum_kata\n";
print "Jumlah kata unik: ". count($arr_kata). "\n";

Python:

import re

f = open('Koleksi.dat', 'r')
arr_kata = {}; str = ''; jum_kata = 0
s = f.readline()
while s:
  str += s
  if s == "</DOC>\n":
    for s in re.findall('<(TITLE|TEXT)>(.+)<\/\\1>', str, re.DOTALL):
      for kata in re.findall('\\b([a-z]+)\\b', s[1].lower(), re.DOTALL):
        if kata in arr_kata: arr_kata[kata] += 1
        else: arr_kata[kata] = 1
        jum_kata += 1
    str = ''
  s = f.readline()

print "Jumlah seluruh kata: ", jum_kata
print "Jumlah kata unik: ", len(arr_kata)

2 Komentar »

  1. Yang menurut saya membuat Delphi lambat di perbadingan tersebut adalah karena OOP-nya. Tiap kali suatu metode virtual di referensi, kompiler perlu menerjemahkan metode tersebut dengan mencari alamatnya di tabel metode virtual. Selain itu pemanggilan Add(0 milik TStringListZ ikut membebani karena memori perlu dialokasi untuk menampung string.

    Perbandingan yang menurut saya fair adalah bila semua nya menggunakan procedural programming.

  2. Dalam perbandingan ini, Delphi menggunakan TPerlRegEx yang berupa library standard PCRE. Sama halnya dengan Python. Melihat kesamaan waktu antara Delphi dan Python, boleh jadi beban komputasi terbesar ada di library tersebut. Perl berada di atas karena dia bisa melakukan optimasi lebih lanjut. PHP terlihat paling tidak efisien dalam transformasi data.

    Perbandingan ini sebenarnya kurang fair, karena Delphi bukan scripting language. Menurut hemat saya, cukup memalukan compiled (machine) code kalah bersaing dengan scripting language. Jangan lupa TStringList sudah di-tuning agar menggunakan ASCII. Perl dalam kapasitas normal UTF-8. Silakan bila ada yang bisa membuktikan Delphi lebih cepat dari Perl dalam Regular Expression.

RSS feed for comments on this post · TrackBack URI

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s