Hub documentation

Otimizações

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Otimizações

Mencionamos brevemente a diferença entre avaliação preguiçosa (lazy) e avaliação imediata (eager). Nesta página, mostraremos como a API preguiçosa (lazy) pode ser usada para obter grandes benefícios de desempenho.

Lazy vs Eager

Polars suporta dois modos de operação: lazy e eager. Na API eager, a consulta é executada imediatamente, enquanto na API lazy a consulta é avaliada apenas quando é “necessária”. Adiar a execução para o último momento pode ter vantagens de desempenho significativas, e é por isso que a API lazy é preferida na maioria dos casos não interativos.

Exemplo

Usaremos o exemplo da página anterior para mostrar os benefícios de desempenho do uso da API lazy. O código abaixo calculará o número de uploads de archive.org.

Eager

import polars as pl
import datetime

df = pl.read_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)

df = df.select("suffix", "crawl", "date", "tld", "pages", "domains")
df = df.filter(
    (pl.col("date") >= datetime.date(2020, 1, 1)) |
    pl.col("crawl").str.contains("CC")
)
df = df.with_columns(
    (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
)
df = df.group_by("tld", "date").agg(
    pl.col("pages").sum(),
    pl.col("domains").sum(),
)
df = df.group_by("tld").agg(
    pl.col("date").unique().count().alias("number_of_scrapes"),
    pl.col("domains").mean().alias("avg_number_of_domains"),
    pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
).sort("avg_number_of_domains", descending=True).head(10)

Lazy

import polars as pl
import datetime

lf = (
    pl.scan_csv("hf://datasets/commoncrawl/statistics/tlds.csv", try_parse_dates=True)
    .filter(
        (pl.col("date") >= datetime.date(2020, 1, 1)) |
        pl.col("crawl").str.contains("CC")
    ).with_columns(
        (pl.col("pages") / pl.col("domains")).alias("pages_per_domain")
    ).group_by("tld", "date").agg(
        pl.col("pages").sum(),
        pl.col("domains").sum(),
    ).group_by("tld").agg(
        pl.col("date").unique().count().alias("number_of_scrapes"),
        pl.col("domains").mean().alias("avg_number_of_domains"),
        pl.col("pages").sort_by("date").pct_change().mean().alias("avg_page_growth_rate"),
    ).sort("avg_number_of_domains", descending=True).head(10)
)
df = lf.collect()

Tempo de execução

Executar ambas as consultas resulta nos seguintes tempos de execução em um laptop comum com uma conexão de internet residencial:

  • Eager: 1.96 segundos
  • Lazy: 410 milissegundos

A consulta preguiçosa é ~5 vezes mais rápida que a consulta imediata. A razão para isso é o otimizador de consultas: se adiarmos a coleta do nosso dataset com collect até o final, o Polars poderá inferir quais colunas e linhas são necessárias e aplicar filtros o mais cedo possível ao ler os dados. Para formatos de arquivo como Parquet que contêm metadados (por exemplo, min, max em um determinado grupo de linhas), a diferença pode ser ainda maior, pois o Polars pode ignorar grupos inteiros de linhas com base nos filtros e nos metadados, sem precisar transmitir os dados pela rede.

Update on GitHub