コンテンツにスキップ
メインメニュー
メインメニュー
サイドバーに移動
非表示
案内
メインページ
GizmoLab 関連
オンラインショップ
CAD&CGブログ
YouTube
GitHub
CAD 系
GizmoTools
AutoLISP
Visual LISP
BricsCADのLISP
GzLib
DCL
OpenDCL
DWG
DXF
CADのコマンド一覧
システム変数
図形の種類
Ver別サポートAPI
CAD用語集
メモ
newLISP
CommonLISP
Script-Fu
Inno setup
JavaScript
ANDROID
Windowsでのファイルハッシュ確認
Prolog
Python
Clojure
Electron
フォント
数学メモ
イメージサイズとメモリ量
blender
Processwire
Win10,11メモ
IIJmio
mediawiki資料
ヘルプ
検索
検索
表示
ログイン
個人用ツール
ログイン
最適化されたコードパターン-BricsCADのソースを表示
ページ
議論
日本語
閲覧
ソースを閲覧
履歴を表示
ツール
ツール
サイドバーに移動
非表示
操作
閲覧
ソースを閲覧
履歴を表示
全般
リンク元
関連ページの更新状況
ページ情報
表示
サイドバーに移動
非表示
←
最適化されたコードパターン-BricsCAD
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
==最適化されたコードパターンの内容== この記事は、Lispファイルのロード時にLispオプティマイザが行う自動的なLispコードの変換についての説明。 左側が元のLispコード、右側が最適化されたコードになっている。 さらに、その理由と効果、BricsCAD Lispエンジンの動作と特殊な条件についての説明もある。 コードパターンの最適化の効果は、専用のLispベンチマークで検証することができる。 ==1. 空の引数とローカル変数のリスト== (defun func ( x y z / ) => (defun func ( x y z ) ) => (defun func ( x y z )) (defun func ( / ) => (defun func ( )) => (defun func ( )) 文字がローカル変数のリストを示すように、defunブロックの内部構造は引数とローカル変数の両方に依存するので、BricsCAD Lispエンジンはローカル変数の識別子をパースする必要がある。 したがって、引数やローカル変数が実質的に存在しない場合、defunコードブロックは軽量な内部構造を使用し、Lispメモリを節約し、実行時のパフォーマンスを向上させることができる。 ==2. (progn ...) 内の単一ステートメント== (progn (setq var 123) ) => (setq var 123) (progn ...) は軽量な操作ではなく、Lispエンジンでは重要な内部操作を引き起こす(他のAutoLISP実装では異なるかもしれない); 単一の式との組み合わせでは (progn ...) は本当の意味を持たないので、これを削除すると性能が向上しメモリ負荷が軽減される。 == 3. 'nil'との比較 == (if (= var nil) ...) => (if (not var) ...) (if (eq var nil) ...) => (if (not var) ...) (if (equal var nil) ...) => (if (not var) ...) (if (/= var nil) ...) => (if (boundp var) ...) 「=」、「eq」、「equal」、「/=」関数を使うと、常に「値による」比較を行うので、「var」変数の内容が評価され、内容の種類(数値、文字列、enameなど)によっては、引数の「nil」と比較される。 nil' との比較は基本的に "var" が *どんな* 内容を持っているかという "論理" (boolean) 操作なので、 (not) resp. (boundp) 関数は "has any content" のようにもっと簡単に比較を行い、内容の種類は重要ではなく、分析もされない。 ===もう一つの利点=== * (not) と (boundp) 関数は共に1つの引数しか取らないので、Lispスタックへの引数のプッシュ/ポップ操作が少なくなり、パフォーマンスも向上する。 == 4. 不要な (progn ...) == (while (expr) (progn ...)) => (while (expr) ...) (repeat (expr) (progn ...)) => (repeat (expr) ...) (foreach item lst (progn ...)) => (foreach item lst ...) while", "repeat", "foreach "のコード全体を囲む(progn ...)は全く必要ありませんが、Lispエンジンに大きなオーバーヘッドを与える(上記参照)ので、この(progn ...)を取り除くことでパフォーマンスが向上し、メモリの負荷も軽減される。 == 5. COM property and method names as strings == (vlax-get-property object "property") => (vlax-get-property object 'property) (vlax-put-property object "property" ...) => (vlax-put-property object 'property ...) (vlax-invoke-method object "method" ...) => (vlax-invoke-method object 'method ...) 文字列名の代わりにシンボル名を使用することで、内部的な利点がある(文字列のコピー操作が少ない、大文字変換が不要)。 == 6. list member access by index == (nth 0 lst) ... (nth 9 lst) => (vle-nth0 lst) ... (vle-nth9 lst) (nth) 関数の使用は非常に一般的なコードで、特に (nth 0 lst), (nth 1 lst) は広く使われているが、(car lst), (cadr) などの関数はより性能が高い。 オプティマイザーはここで、インデックス 0...9 に対して (vle-nth) 関数を使用する。 特にループの中で(nth 0 lst)などを使うと、驚くほど性能が向上する。これは、(vle-nth)関数の引数が2つでなく1つだけなので、Lispスタックのpush/pop操作が少なくなるためである。 == 7. (cdr (assoc ...)) == (cdr (assoc item lst)) => (vle-cdrassoc item lst) (cdr (assoc ...)) はどのLisp言語でも見られる最も基本的なコードパターンです。しかし、最近のLisp言語はこの基本的な操作のために専用の関数cassoc(または同様のもの)を持っている。 # 2つのLisp命令ではなく、1つのLisp命令で済むので、50%以上の性能向上が期待できる。 # (assoc)処理による一時的なLisp結果がなく、(cdr)処理後はゴミとなる。 == 8. (reverse (cdr (reverse ..))) == (reverse (cdr (reverse lst)) => (vle-remove-last lst) もう一つの最も基本的な操作は、リストの最後の項目を削除することである。残念ながら、AutoLISPは(最近のLispのように)関連する関数を提供していないため、開発者はこの非常に非効率なコードを使用する以外に選択肢がないのである。 BricsCAD Lispでは(vle-remove-last)関数を提供しており、その性能向上は非常に大きい。 # 3つの操作の代わりに、1つの操作のみ # 一時的な中間リストが2つ作成されない。元のコードでは2つのリストが作成され、コストがかかり、無駄なメモリ負荷とGarbageCollectionsが増加する。 == 9. (cdr (assoc dxf (entget ...))) == (cdr (assoc dxf (entget ename))) => (vle-entget dxf ename) CAD環境では、このコードパターンも非常に基本的で、最もよく使われる。ここで、性能と効率を向上させるために、Lispエンジンは、(vle-entget)関数を提供する。 # 3つの操作の代わりに1つの操作のみ # (entget)と(assoc)による一時データの作成が完全に回避される。エンティティ定義データはかなり大きいので、これらのデータの作成は非常にコストがかかり、使用したメモリはその後すぐにゴミとなる。 == 10. (tblsearch) のブーリアン使用 == (not (tblsearch table item)) => (not (vle-tblsearch table item)) (null (tblsearch table item)) => (null (vle-tblsearch table item)) (if (tblsearch table item) ...) => (if (vle-tblsearch table item)) ... (and (tblsearch table item) ...) => (and (vle-tblsearch table item) ...) (or (tblsearch table item) ...) => (or (vle-tblsearch table item) ...) (while (tblsearch table item) ...) => (while (vle-tblsearch table item) ...) このコードパターンも非常に基本的で、特定のテーブル項目が存在するかどうかを確認するために最もよく使用される。 この部分のパフォーマンスと効率を改善するために、Lispエンジンは(vle-tblsearch)関数を提供している。 この最適化により、実行時間が大幅に短縮され、メモリ使用量も削減される(したがって、ガベージコレクションの発生も少なくなる)。 注: すべてのAutoLISP互換システムには、ネイティブの(tblobjname)もあり、ここでも使用できる。 == 11. (dictsearch) のブーリアン使用 == (not (dictsearch dict item)) => (not (vle-dictsearch dict item)) (null (dictsearch dict item)) => (null (vle-dictsearch dict item)) (if (dictsearch dict item) ...) => (if (vle-dictsearch dict item) ...) (and (dictsearch dict item) ...) => (and (vle-dictsearch dict item) ...) (or (dictsearch dict item) ...) => (or (vle-dictsearch dict item) ...) (while (dictsearch dict item) ...) => (while (vle-dictsearch dict item) ...) このコードパターンも非常に基本的で、特定の辞書項目が存在するかどうかを確認するために最もよく使用される。 ここでの性能と効率を改善するために、Lispエンジンは(vle-dictsearch)関数を提供している。 この最適化により、実行時間が大幅に短縮され、メモリ使用量も削減される(したがって、GarbageCollectionsの発生も少なくなる)。 注: (vle-dictobjname)もあり、こちらも同様に使用できる(他のCADシステムでもエミュレーションで使用できる)。 == 12. (entget) のブーリアン使用 == (not (entget ename)) => (not (vle-ename-valid ename)) (null (entget ename)) => (null (vle-ename-valid ename)) (if (entget ename) ...) => (if (vle-ename-valid ename) ...) (and (entget ename) ...) => (and (vle-ename-valid ename) ...) (or (entget ename) ...) => (or (vle-ename-valid ename) ...) (while (entget ename) ...) => (while (vle-ename-valid ename) ...) このコードパターンも非常に基本的で、与えられたエンティティが有効で消去されていないかどうかを確認するために最もよく使われます。この部分のパフォーマンスと効率を改善するために、Lispエンジンは (vle-ename-valid) 関数を提供します。 この最適化により、実行時間の大幅な短縮とメモリ使用量の削減(GarbageCollectionの発生を抑える)が可能となる。 """BricsCADのテストシステムは、これらのすべてのケースをカバーし、正常な動作を保証している。"""
最適化されたコードパターン-BricsCAD
に戻る。
検索
検索
最適化されたコードパターン-BricsCADのソースを表示
話題を追加