Pixel Pedals of Tomakomai

北海道苫小牧市出身の初老の日常

ChatGPT とプログラミング

ChatGPT にプログラムを書かせることには否定的なのだが、それでもやはり便利だ。特に、普段は触ることのない環境でコードを書くための足掛かりを手っ取り早く掴むためには最良の手段と言える。

例えば、 Windows の Power Shell 上で .exe ファイルの処理にかかる時間を計測するスクリプトを書かせると、こんなものが返ってきた。もちろん、正しく動く。

# 測定したいEXEファイルのパス
$exePath = "C:\path\to\your\executable.exe"

# 処理時間の計測
$executionTime = Measure-Command {
    # EXEファイルの実行
    & $exePath
}

# 処理時間の表示
Write-Host "Execution Time: $($executionTime.TotalMilliseconds) milliseconds"

どんな名前で保存すればいいかも分からなかったので聞くと、こんな答え。

PowerShell スクリプトの標準的な拡張子は .ps1 です。したがって、ファイル名は sample.ps1 のようにするのが適切です。

メモリ使用量も知りたいと思い、書かせたスクリプトがこれ。

# EXEファイルのパス
$exePath = "C:\path\to\your\executable.exe"

# プロセスの起動
$process = Start-Process -FilePath $exePath -PassThru

# メモリ使用量の監視
$maxMemory = 0
while (-not $process.HasExited) {
    $process.Refresh()
    $currentMemory = $process.WorkingSet64
    if ($currentMemory -gt $maxMemory) {
        $maxMemory = $currentMemory
    }
    Start-Sleep -Milliseconds 500
}

# 結果の表示
Write-Host "Maximum Memory Usage: $($maxMemory / 1MB) MB"

もちろん、 google 検索をすれば同じ効果は得られるのだろうが、その場合は、

  1. 検索結果の URL から、適切そうなものを選び出す
  2. URL 先のページに飛び、目的のコードが書かれている箇所を探す

というステップが必要となる。 ChatGPT にやらせることで、このステップを大幅に短縮することができる。

もっとも、先に述べた通り ChatGPT にまともなコードを書かせるのには懐疑的で、例えば、巨大な JSON ファイルの一部をストリーミングする Rust のコードを生成させたのだが、何度か指示を繰り返しても以下が限界だった。

// ※ ChatGPT4 が生成した、動作しないコード ※

use serde::{Deserialize, de};
use serde_json::{self, Deserializer, Value};
use std::fs::File;
use std::io::BufReader;

// カスタムビジターの定義
struct ListVisitor;

impl<'de> de::Visitor<'de> for ListVisitor {
    type Value = ();

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str("an array of items")
    }

    // 配列の各要素に対する処理を実装
    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: de::SeqAccess<'de>,
    {
        while let Some(item) = seq.next_element::<Value>()? {
            // ここで配列の各要素に対する処理を行う
            // 例: `println!("{:?}", item);`
        }
        Ok(())
    }
}

fn main() -> serde_json::Result<()> {
    let file = File::open("path/to/your/large_file.json")?;
    let reader = BufReader::new(file);
    let mut deserializer = Deserializer::from_reader(reader);

    // `list`フィールドを探す
    let mut found = false;
    while !found {
        // ストリーミングデシリアライザでJSONを逐次処理
        let value = Value::deserialize(&mut deserializer)?;
        match value {
            Value::Object(obj) => {
                if let Some(list) = obj.get("list") {
                    found = true;
                    list.deserialize_seq(ListVisitor)?;
                }
            },
            _ => continue,
        }
    }

    Ok(())
}

Value オブジェクトを作ってしまっており、ファイルのデータをすべてメモリに展開していることになる。逐次処理にはなっていない。最初は Visitor も使うことができていなかったので、それを提案したら、

はい、Rustのserde_jsonライブラリを使用して、"list"フィールドが含む配列を逐次処理するためのカスタムビジターを定義する方法で問題を解決できます。

と自信満々に答えていたのだが、やはり正しく使えていない。

正解は、一年前に自分が書いた以下のコードのように Visitor 内で処理した上で、サマリを deserialize させる必要がある。

github.com