Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Indent Performance: string/comment lookups

オープン
#407 コメント 13 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
28/100
issue の種類
リファクタリング
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
elixir, vim

調査の方向性

elixir#indent#indent() と elixir#indent#handle_inside_nested_construct() から始め、77_is_string_or_comment() と elixir#indent#searchpair_back_skip() の反復呼び出しをプロファイリングします。前処理または検索の削減を行う前後でインデントの動作を比較します。正しいインデントを維持しながら、文字列/コメント検索の反復コストを削減できれば完了です。

索引モデルが issue の本文から書いたものです。

説明

enhancement HIGH-PRIORITY indent maybe-fixed?

Given the following file:

defmodule Http do
  defmacro __using__(_) do
    quote do
      use HTTPoison.Base

      def get(url, headers \\ [], options \\ []) do
        response(:get, url, "", headers, options)
      end

      def delete(url, headers \\ [], options \\ []) do
        response(:delete, url, "", headers, options)
      end

      def post(url, body, headers \\ [], options \\ []) do
        response(:post, url, body, headers, options)
      end

      def patch(url, body, headers \\ [], options \\ []) do
        response(:patch, url, body, headers, options)
      end

      def response(method, url, body, headers \\ [], options \\ []) do
        url = options.base_url <> url
        log(method, :start, url, options)
        start_time = now()

        response = request(method, url, body, headers, options)

        case response do
          {:ok, response} ->
            log(method, :finish, url, options, response, start_time)

          {:error, response} ->
            log(method, :error, url, options, response, start_time)
        end

        response
      end

      def process_request_options(%_{} = options) do
        options
        |> Map.from_struct()
        |> Enum.into([])
        |> process_request_options()
      end

      def process_request_options(options) do
        [
          timeout: 10_000,
          recv_timeout: 15_000,
          hackney: [pool: :http_default_pool]
        ]
        |> Keyword.merge(options)
      end

      def process_request_body(body) when is_map(body), do: Poison.encode!(body)
      def process_request_body(body) when is_binary(body), do: body

      def process_response_body(body) do
        case Poison.Parser.parse(body) do
          {:ok, parsed_body} -> parsed_body
          {:error, _} -> body
        end
      end

      def process_request_headers(headers) do
        headers
      end

      defp now(), do: DateTime.utc_now() |> DateTime.to_unix(:millisecond)

      defp log(request_method, at, path, options, response \\ nil, started_at \\ nil) do
        data = %{
          api_request: true,
          at: at,
          host: options.base_url,
          request_id: options.request_id,
          url: path,
          method: request_method,
          path: options.generic_path,
          elapsed: started_at && now() - started_at
          # status: response && response.status_code,
          # reason: response && response.reason
        }

        # remove keys with falsy values
        data = for {key, value} <- data, value, into: %{}, do: {key, value}

        case response do
          nil -> Plexy.Logger.debug(data)
          %HTTPoison.Response{} -> Plexy.Logger.debug(data)
          %HTTPoison.Error{} = error -> Plexy.Logger.error(data)
        end
      end
    end
  end
end

We get the following profiler output:

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
 9466             10.457848  <SNR>77_is_string_or_comment()
  312  11.036247   1.915420  elixir#indent#handle_inside_nested_construct()
 8828   9.363995   0.120360  elixir#indent#searchpair_back_skip()
 1522   1.123686   0.106535  <SNR>77_ends_with()
  384  13.163921   0.071142  elixir#indent#indent()
   52   0.205268   0.054884  elixir#indent#handle_inside_generic_block()
  382   0.210430   0.053353  elixir#indent#handle_starts_with_end()
 2542   0.096197   0.048705  <SNR>77_starts_with()
  398  61.177775   0.024607  <SNR>77_get_base_indent()
  326   0.164678   0.021031  elixir#indent#handle_starts_with_close_bracket()
 4644              0.017567  <SNR>77_debug()
  312   0.018112   0.006850  elixir#indent#handle_starts_with_binary_operator()
  334   0.020190   0.006785  elixir#indent#handle_starts_with_pipe()
  358   0.013070   0.005970  elixir#indent#handle_starts_with_mid_or_end_block_keyword()
  358   0.087979   0.005809  elixir#indent#handle_following_trailing_do()
  334   0.037895   0.003777  elixir#indent#handle_following_trailing_binary_operator()
  230              0.003508  elixir#indent#handle_starts_with_comment()
    8              0.003288  <SNR>77_find_last_pos()
  384  13.166979   0.003058  elixir#indent()
 1274              0.002925  <SNR>77_keyword()

The clear culprit is delegating to the syntax engine over and over. One thought - can we filter out all of the strings in a preprocessing step perhaps? That would surely be cheaper than checking them over and over

主要言語
Ruby
スター
1.3k
フォーク
154
PR マージ指標
30日以内にマージされた PR はありません

環境構築

  • Dockerfile または Docker Compose ファイルあり
  • プルリクエストのテンプレートなし
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

elixir-editors/vim-elixir のほかの issue

elixir-editors/vim-elixir の issue をすべて見る

似ている issue

Ruby の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。