Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack overflow on Windows #2857

Open
eitsupi opened this issue Jun 18, 2023 · 30 comments · Fixed by #2878
Open

Stack overflow on Windows #2857

eitsupi opened this issue Jun 18, 2023 · 30 comments · Fixed by #2878
Labels
bug Invalid compiler output or panic compiler

Comments

@eitsupi
Copy link
Member

eitsupi commented Jun 18, 2023

See #2700 (comment) and #2713 and #2781 (comment)


I tried a few simple examples with the latest prqlc.exe built from main (8f9b778), and I suspect that this has nothing to do with count and everything to do with the number of filter and take and sort.

Working

from employees
filter gross_cost > 0
group {title} (
  aggregate {
    ct = count s"*",
  }
)
sort ct
filter ct > 200
from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
filter ct > 200
sort ct
filter ct > 200
sort ct

Not working

from employees
filter gross_cost > 0
group {title} (
  aggregate {
    ct = count s"*",
  }
)
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
from employees
filter gross_cost > 0
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
sort ct
filter ct > 200
take 20
from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
filter ct > 200
sort ct
filter ct > 200
sort ct
filter ct > 200

Originally posted by @eitsupi in #2717 (comment)

@max-sixty
Copy link
Member

Ah, great discovery!

Does prqlc parse fail too? I would have thought it were the parser...

@eitsupi
Copy link
Member Author

eitsupi commented Jun 18, 2023

Does prqlc parse fail too? I would have thought it were the parser...

No, it seems working.

❯ ./prqlc.exe parse
Enter PRQL, then press ctrl-z to compile:

from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
filter ct > 200
sort ct
filter ct > 200
sort ct
filter ct > 200

sources:
  '':
  - name: main
    VarDef:
      value:
        Pipeline:
          exprs:
          - FuncCall:
              name:
                Ident:
                - from
              args:
              - Ident:
                - employees
          - FuncCall:
              name:
                Ident:
                - filter
              args:
              - Binary:
                  left:
                    Ident:
                    - gross_cost
                  op: Gt
                  right:
                    Literal: !Integer 0
          - FuncCall:
              name:
                Ident:
                - take
              args:
              - Literal: !Integer 20
          - FuncCall:
              name:
                Ident:
                - sort
              args:
              - Ident:
                - ct
          - FuncCall:
              name:
                Ident:
                - filter
              args:
              - Binary:
                  left:
                    Ident:
                    - ct
                  op: Gt
                  right:
                    Literal: !Integer 200
          - FuncCall:
              name:
                Ident:
                - sort
              args:
              - Ident:
                - ct
          - FuncCall:
              name:
                Ident:
                - take
              args:
              - Literal: !Integer 20
          - FuncCall:
              name:
                Ident:
                - filter
              args:
              - Binary:
                  left:
                    Ident:
                    - ct
                  op: Gt
                  right:
                    Literal: !Integer 200
          - FuncCall:
              name:
                Ident:
                - sort
              args:
              - Ident:
                - ct
          - FuncCall:
              name:
                Ident:
                - filter
              args:
              - Binary:
                  left:
                    Ident:
                    - ct
                  op: Gt
                  right:
                    Literal: !Integer 200
          - FuncCall:
              name:
                Ident:
                - sort
              args:
              - Ident:
                - ct
          - FuncCall:
              name:
                Ident:
                - filter
              args:
              - Binary:
                  left:
                    Ident:
                    - ct
                  op: Gt
                  right:
                    Literal: !Integer 200
      ty_expr: null
      kind: Main
    annotations: []
source_ids:
  0: ''
❯ ./prqlc.exe compile
Enter PRQL, then press ctrl-z to compile:

from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
filter ct > 200
sort ct
filter ct > 200
sort ct
filter ct > 200

thread 'main' has overflowed its stack

@max-sixty
Copy link
Member

Oh, weird, thanks. So it's likely in "our" code rather than Chumsky.

If you have the patience (no problem if you're busy; I don't have access to a Windows machine unfortunately), would you mind running with RUST_LOG=trace RUST_BACKTRACE=full env vars?

And if that's unclear, we could see how far we can get before overflowing — for example whether prqlc resolve works...

@eitsupi
Copy link
Member Author

eitsupi commented Jun 18, 2023

If you have the patience (no problem if you're busy; I don't have access to a Windows machine unfortunately), would you mind running with RUST_LOG=trace RUST_BACKTRACE=full env vars?

Sure.

$env:RUST_LOG='trace'$env:RUST_BACKTRACE='full'
❯ ./prqlc.exe compile
Enter PRQL, then press ctrl-z to compile:

from employees
filter gross_cost > 0
take 20
sort ct
filter ct > 200
sort ct
take 20
filter ct > 200
sort ct
filter ct > 200
sort ct
filter ct > 200

log.txt

for example whether prqlc resolve works...

Also does not work.

@max-sixty
Copy link
Member

Thanks! It looks like it's failing somewhere in the resolver; the final trace is at

log::debug!("... which is {entry}");

I wouldn't have thought that there are enough items on the stack at that point to get close to overflow. But it also presumably can't enter an infinite loop given it on overflows on Windows...

@eitsupi
Copy link
Member Author

eitsupi commented Jun 19, 2023

@max-sixty
Copy link
Member

Great find @eitsupi ! That seems likely. So I guess one of our structs is huge (and this isn't fortran!).

So it's about the size of objects on the stack, rather than having a very long call-chain. I'll have a look at what this might be (unless @aljazerzen sees this and have a good idea what this is likely to be).

And then probably we can just put that thing in a Box — the performance hit would be trivial.

@aljazerzen
Copy link
Member

I'm not sure if this is fixed, can someone on Windows verify?

@eitsupi
Copy link
Member Author

eitsupi commented Jun 20, 2023

I'm not sure if this is fixed, can someone on Windows verify?

As I wrote here (#2878 (comment)), I tried several queries.
One of the three seems to compile correctly now, thanks!

Is there anything else I can do?

@aljazerzen
Copy link
Member

I don't know how to debug this. If you are comfortable with Rust and traits, you I have a few ideas that might work, but require tweaking the parser. Which is always fun \s.

@max-sixty
Copy link
Member

As I wrote here (#2878 (comment)), I tried several queries. One of the three seems to compile correctly now, thanks!

Thanks for trying. I hadn't realized that was with the current version.

Is there anything else I can do?

One thing we could do @eitsupi is to add these as tests, to test.rs. Then we don't need to ask you to test each query :)

(I can do that if you don't get to it)


That said, I do think this will be difficult without the unification of a Windows box and @aljazerzen 's mind! I can have a go though, maybe bring a fresh perspective...

We can also rent Windows VMs — the cost is the setup rather than the $ cost

@aljazerzen
Copy link
Member

unification of a Windows box and @aljazerzen 's mind!

Oh, I do have a windows box, but I'm not willing to pay the setup cost. And also I have ideological objections to using windows :D

@eitsupi
Copy link
Member Author

eitsupi commented Jun 21, 2023

As I wrote #2894 (comment), it seems still failing.

@eitsupi eitsupi reopened this Jun 21, 2023
@eitsupi
Copy link
Member Author

eitsupi commented Jun 21, 2023

This problem seems to still occur, but has definitely been improved by #2878.

I have confirmed that this query, where this problem was discovered, also compiles correctly.
So perhaps this problem is rarely encountered in normal use and we can keep this open.

@max-sixty max-sixty changed the title Stack Overflow on Windows Stack overflow on Windows Jun 22, 2023
@max-sixty
Copy link
Member

I did some quick diagnostics. Using this diff from the current main (similar to #2908 but uses an unstable feature):

diff --git a/prql-compiler/prqlc/tests/project/Project.prql b/prql-compiler/prqlc/tests/project/Project.prql
index 1fc6a97f..1b44377f 100644
--- a/prql-compiler/prqlc/tests/project/Project.prql
+++ b/prql-compiler/prqlc/tests/project/Project.prql
@@ -6,3 +6,4 @@ let favorite_artists = [
 
 favorite_artists
 join artists.input side:left (==artist_id)
+join long_query.long_query side:left (input.title == long_query.title)
diff --git a/prql-compiler/prqlc/tests/project/long_query.prql b/prql-compiler/prqlc/tests/project/long_query.prql
new file mode 100644
index 00000000..9f64f091
--- /dev/null
+++ b/prql-compiler/prqlc/tests/project/long_query.prql
@@ -0,0 +1,25 @@
+# TODO: move this into a separate test; but putting here because of the
+# `insta_cmd` issues, and because we're in a rush to ensure Windows builds
+# aren't randomly breaking.
+
+let long_query = (
+    from employees
+    filter gross_cost > 0
+    group {title} (
+        aggregate {
+            ct = count s"*",
+        }
+    )
+    sort ct
+    filter ct > 200
+    take 20
+    sort ct
+    filter ct > 200
+    take 20
+    sort ct
+    filter ct > 200
+    take 20
+    sort ct
+    filter ct > 200
+    take 20
+)
diff --git a/prql-compiler/prqlc/tests/test.rs b/prql-compiler/prqlc/tests/test.rs
index d495b301..37c65cd1 100644
--- a/prql-compiler/prqlc/tests/test.rs
+++ b/prql-compiler/prqlc/tests/test.rs
@@ -78,77 +78,7 @@ fn test_compile_project() {
     cmd.arg(project_path());
     cmd.arg("-");
     cmd.arg("main");
-    assert_cmd_snapshot!(cmd, @r###"
-    success: true
-    exit_code: 0
-    ----- stdout -----
-    WITH table_1 AS (
-      SELECT
-        120 AS artist_id,
-        DATE '2023-05-18' AS last_listen
-      UNION
-      ALL
-      SELECT
-        7 AS artist_id,
-        DATE '2023-05-16' AS last_listen
-    ),
-    favorite_artists AS (
-      SELECT
-        artist_id,
-        last_listen
-      FROM
-        table_1
-    ),
-    table_0 AS (
-      SELECT
-        *
-      FROM
-        read_parquet('artists.parquet')
-    ),
-    input AS (
-      SELECT
-        *
-      FROM
-        table_0
-    )
-    SELECT
-      favorite_artists.artist_id,
-      favorite_artists.last_listen,
-      input.*
-    FROM
-      favorite_artists
-      LEFT JOIN input ON favorite_artists.artist_id = input.artist_id
-
-    ----- stderr -----
-    "###);
-
-    let mut cmd = prqlc_command();
-    cmd.args(["compile", "--hide-signature-comment"]);
-    cmd.arg(project_path());
-    cmd.arg("-");
-    cmd.arg("favorite_artists");
-    assert_cmd_snapshot!(cmd, @r###"
-    success: true
-    exit_code: 0
-    ----- stdout -----
-    WITH table_0 AS (
-      SELECT
-        120 AS artist_id,
-        DATE '2023-05-18' AS last_listen
-      UNION
-      ALL
-      SELECT
-        7 AS artist_id,
-        DATE '2023-05-16' AS last_listen
-    )
-    SELECT
-      artist_id,
-      last_listen
-    FROM
-      table_0
-
-    ----- stderr -----
-    "###);
+    assert_cmd_snapshot!(cmd);
 }
 
 #[test]
@@ -162,7 +92,7 @@ fn test_format() {
     ----- stdout -----
 
     ----- stderr -----
-    Currently `fmt` only works with a single source, but found multiple sources: "`Project.prql`, `artists.prql`"
+    Currently `fmt` only works with a single source, but found multiple sources: "`Project.prql`, `artists.prql`, `long_query.prql`"
     "###);
 }
 
@@ -189,8 +119,8 @@ fn prqlc_command() -> Command {
     // `--color=never` flag.
     cmd.env_remove("CLICOLOR_FORCE");
     // We don't want the tests to be affected by the user's `RUST_BACKTRACE` setting.
-    cmd.env_remove("RUST_BACKTRACE");
-    cmd.env_remove("RUST_LOG");
+    // cmd.env_remove("RUST_BACKTRACE");
+    // cmd.env_remove("RUST_LOG");
     cmd.args(["--color=never"]);
     cmd
 }
diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs
index dacfd237..aeb270df 100644
--- a/prql-compiler/src/lib.rs
+++ b/prql-compiler/src/lib.rs
@@ -65,7 +65,7 @@
 //!     $ prqlc compile query.prql
 //!     ```
 //!
-
+#![feature(backtrace_frames)]
 #![forbid(unsafe_code)]
 // Our error type is 128 bytes, because it contains 5 strings & an Enum, which
 // is exactly the default warning level. Given we're not that performance
diff --git a/prql-compiler/src/semantic/module.rs b/prql-compiler/src/semantic/module.rs
index 97b08a17..b86c7693 100644
--- a/prql-compiler/src/semantic/module.rs
+++ b/prql-compiler/src/semantic/module.rs
@@ -1,4 +1,7 @@
-use std::collections::{HashMap, HashSet};
+use std::{
+    backtrace,
+    collections::{HashMap, HashSet},
+};
 
 use anyhow::{bail, Result};
 use itertools::Itertools;
@@ -201,6 +204,12 @@ fn lookup_in(module: &Module, ident: Ident) -> HashSet<Ident> {
         }
 
         log::trace!("lookup: {ident}");
+        let bt = backtrace::Backtrace::capture();
+        let len = bt.frames().len();
+        log::trace!("{}", len);
+        if len >= 120 {
+            log::trace!("{:?}", bt);
+        }
 
         let mut res = HashSet::new();
 

And then running with:

RUST_BACKTRACE=1 RUST_LOG=trace cargo +nightly insta test --accept -p prqlc  -- project

We can then look at how deep the stack traces are with:

 rg '\]\s(\d+)$' -o -r '$1' -N prql-compiler/prqlc/tests/snapshots/test__compile_project.snap | sort -n

I then set some bound at which to log the whole stack trace (currently 120 deep), and then looked at one:

[TRACE prql_compiler::semantic::module] Backtrace [{ fn: "std::backtrace_rs::backtrace::libunwind::trace", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/../../backtrace/src/backtrace/libunwind.rs", line: 93 }, { fn: "std::backtrace_rs::backtrace::trace_unsynchronized", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/../../backtrace/src/backtrace/mod.rs", line: 66 }, { fn: "std::backtrace::Backtrace::create", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/backtrace.rs", line: 332 }, { fn: "prql_compiler::semantic::module::Module::lookup", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/module.rs", line: 207 }, { fn: "prql_compiler::semantic::module::Module::lookup::lookup_in", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/module.rs", line: 171 }, { fn: "prql_compiler::semantic::module::Module::lookup", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/module.rs", line: 220 }, { fn: "prql_compiler::semantic::context::Context::resolve_ident_fallback", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/context.rs", line: 214 }, { fn: "prql_compiler::semantic::context::Context::resolve_ident_fallback", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/context.rs", line: 219 }, { fn: "prql_compiler::semantic::context::Context::resolve_ident", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/context.rs", line: 195 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_ident", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 519 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 196 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_type_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 906 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_ty_or_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 920 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function_types::{{closure}}", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 687 }, { fn: "core::iter::adapters::map::map_try_fold::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/map.rs", line: 91 }, { fn: "core::iter::traits::iterator::Iterator::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 2303 }, { fn: "<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/map.rs", line: 117 }, { fn: "<core::iter::adapters::GenericShunt<I,R> as core::iter::traits::iterator::Iterator>::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/mod.rs", line: 195 }, { fn: "<I as alloc::vec::in_place_collect::SpecInPlaceCollect<T,I>>::collect_in_place", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/in_place_collect.rs", line: 258 }, { fn: "alloc::vec::in_place_collect::<impl alloc::vec::spec_from_iter::SpecFromIter<T,I> for alloc::vec::Vec>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/in_place_collect.rs", line: 182 }, { fn: "<alloc::vec::Vec as core::iter::traits::collect::FromIterator>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/mod.rs", line: 2711 }, { fn: "core::iter::traits::iterator::Iterator::collect", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 1895 }, { fn: "<core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/result.rs", line: 1932 }, { fn: "core::iter::adapters::try_process", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/mod.rs", line: 164 }, { fn: "<core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/result.rs", line: 1932 }, { fn: "core::iter::traits::iterator::Iterator::collect", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 1895 }, { fn: "itertools::Itertools::try_collect", file: "/Users/maximilian/.cargo/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.10.5/src/lib.rs", line: 2014 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function_types", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 682 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 229 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 267 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 306 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_type_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 906 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_ty_or_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 920 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function_types::{{closure}}", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 687 }, { fn: "core::iter::adapters::map::map_try_fold::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/map.rs", line: 91 }, { fn: "core::iter::traits::iterator::Iterator::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 2303 }, { fn: "<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/map.rs", line: 117 }, { fn: "<core::iter::adapters::GenericShunt<I,R> as core::iter::traits::iterator::Iterator>::try_fold", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/mod.rs", line: 195 }, { fn: "<I as alloc::vec::in_place_collect::SpecInPlaceCollect<T,I>>::collect_in_place", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/in_place_collect.rs", line: 258 }, { fn: "alloc::vec::in_place_collect::<impl alloc::vec::spec_from_iter::SpecFromIter<T,I> for alloc::vec::Vec>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/in_place_collect.rs", line: 182 }, { fn: "<alloc::vec::Vec as core::iter::traits::collect::FromIterator>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/alloc/src/vec/mod.rs", line: 2711 }, { fn: "core::iter::traits::iterator::Iterator::collect", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 1895 }, { fn: "<core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/result.rs", line: 1932 }, { fn: "core::iter::adapters::try_process", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/adapters/mod.rs", line: 164 }, { fn: "<core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/result.rs", line: 1932 }, { fn: "core::iter::traits::iterator::Iterator::collect", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/iter/traits/iterator.rs", line: 1895 }, { fn: "itertools::Itertools::try_collect", file: "/Users/maximilian/.cargo/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.10.5/src/lib.rs", line: 2014 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function_types", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 682 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 229 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 267 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 799 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_within_namespace", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 847 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_and_type_check", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 818 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_function_args", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 760 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_function", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 584 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 274 }, { fn: "prql_compiler::semantic::resolver::Resolver::resolve_pipeline", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 510 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 279 }, { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_var_def", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 168 }, { fn: "prql_compiler::semantic::resolver::Resolver::fold_statements", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 78 }, { fn: "prql_compiler::semantic::resolve", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/mod.rs", line: 62 }, { fn: "prql_compiler::semantic::resolve_and_lower", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/mod.rs", line: 31 }, { fn: "prql_compiler::pl_to_rq_tree", file: "/Users/maximilian/workspace/prql/prql-compiler/src/lib.rs", line: 282 }, { fn: "prqlc::cli::Command::execute::{{closure}}", file: "./src/cli.rs", line: 350 }, { fn: "core::result::Result<T,E>::and_then", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/result.rs", line: 1319 }, { fn: "prqlc::cli::Command::execute", file: "./src/cli.rs", line: 349 }, { fn: "prqlc::cli::Command::run_io_command", file: "./src/cli.rs", line: 238 }, { fn: "prqlc::cli::Command::run", file: "./src/cli.rs", line: 217 }, { fn: "prqlc::cli::main", file: "./src/cli.rs", line: 37 }, { fn: "prqlc::main", file: "./src/main.rs", line: 16 }, { fn: "core::ops::function::FnOnce::call_once", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/ops/function.rs", line: 250 }, { fn: "std::sys_common::backtrace::__rust_begin_short_backtrace", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/sys_common/backtrace.rs", line: 135 }, { fn: "std::rt::lang_start::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/rt.rs", line: 166 }, { fn: "core::ops::function::impls::<impl core::ops::function::FnOnce for &F>::call_once", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/core/src/ops/function.rs", line: 284 }, { fn: "std::panicking::try::do_call", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panicking.rs", line: 500 }, { fn: "std::panicking::try", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panicking.rs", line: 464 }, { fn: "std::panic::catch_unwind", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panic.rs", line: 142 }, { fn: "std::rt::lang_start_internal::{{closure}}", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/rt.rs", line: 148 }, { fn: "std::panicking::try::do_call", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panicking.rs", line: 500 }, { fn: "std::panicking::try", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panicking.rs", line: 464 }, { fn: "std::panic::catch_unwind", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/panic.rs", line: 142 }, { fn: "std::rt::lang_start_internal", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/rt.rs", line: 148 }, { fn: "std::rt::lang_start", file: "/rustc/498553fc04f6a3fdc53412320f4e913bc53bc267/library/std/src/rt.rs", line: 165 }, { fn: "_main" }]

It looks like the resolver goes very deep. Is that because it structures foo | bar | baz as baz(bar(foo)), such that a long query is a very deeply nested query?

...rather than working like an intepreter, evaluating r0=bar(foo) and then baz(r0)?

If so — that's an elegant approach, but maybe it scales badly with program size?


I need to sign off for a bit, and probably won't be doing much coding in the next couple of days. I can look at this more after that though!

@max-sixty
Copy link
Member

max-sixty commented Jun 24, 2023

One way of emulating this on a Mac — run ulimit -s 1024, and then cargo test in the same shell.

At 512, doctests fail (not sure why this is different?). But otherwise only the prqlc test fails.

@max-sixty
Copy link
Member

FYI this was fixed and then started reoccurring again after #3786.

I'll try and open a PR with the test reenabled to track if it's still an issue

@max-sixty
Copy link
Member

@aljazerzen I've been thinking about this some more. Is this a fundamental limitation with our compiling approach? Or is there some way of getting around it?

It looks like the resolver goes very deep. Is that because it structures foo | bar | baz as baz(bar(foo)), such that a long query is a very deeply nested query?

...rather than working like an interpreter, evaluating r0=bar(foo) and then baz(r0)?

If so — that's an elegant approach, but maybe it scales badly with program size?

@aljazerzen
Copy link
Member

I doubt this is a fundamantally bad approach - I've parsed enormous PRQL files with a relatively small stack size, so I don't think it applies to Linux too.

@max-sixty
Copy link
Member

I doubt this is a fundamantally bad approach - I've parsed enormous PRQL files with a relatively small stack size, so I don't think it applies to Linux too.

OK interesting. Though FYI am guessing this is the case for Linux too:

One way of emulating this on a Mac — run ulimit -s 1024, and then cargo test in the same shell.

...in which case this is a magnitude rather than a categorical issue. (only in dev mode though, not with --release)

@aljazerzen
Copy link
Member

1MB of stack memory is not that much. When I was trying this out and have limited stack size on Linux, prqlc started failing in resolver, so I concluded it is not a problem at all. I was using a test file where I just added a bunch of take 10 and filter true lines to make it massive.

@aljazerzen
Copy link
Member

There is only one solution to this problem: install Windows somewhere and debug it. Until we try that there is no point in trying other solutions.

@max-sixty
Copy link
Member

1MB of stack memory is not that much.

IIUC Windows has a 1-2MB default stack size, which is why we get this problem on Windows or when reducing the stack size on Mac...

I was using a test file where I just added a bunch of take 10 and filter true lines to make it massive.

Yes, we have this test which does something similar: https://github.com/PRQL/prql/pull/4073/files

There is only one solution to this problem: install Windows somewhere and debug it. Until we try that there is no point in trying other solutions.

If I set a similar stack size to Windows' I get the same error, described here: #2857 (comment).

And that shows that we're 120 frames deep when overflowing the stack, mostly from the resolver. I don't know if that's bad per se, but it does seem to be the cause of the issue.

Isn't that a pretty good test? Or there's a case for it being different on Windows?

@aljazerzen
Copy link
Member

Isn't that a pretty good test? Or there's a case for it being different on Windows?

I don't know if it is, because we don't know what's really the problem.


I've setup a Windows VM, downloaded git, rust toolchain and prql, compiled prqlc and parsed the test file.

I'm not able to reproduce this error.
Commands used:

cargo run -p prqlc -- parse _a.prql

Maybe it is a problem of available memory size?

@max-sixty
Copy link
Member

max-sixty commented Jan 16, 2024

I've setup a Windows VM, downloaded git, rust toolchain and prql, compiled prqlc and parsed the test file.

!!

I'm not able to reproduce this error.

Does cargo test pass after this change: https://github.com/PRQL/prql/pull/4073/files ?

@aljazerzen
Copy link
Member

The test does fail. Which is strange, so I re-ran it from the command line with compile instead of parse and now it fails too.

A few observations:

  • it does not happen during parsing,

  • it happens in prqlc/prql-compiler/src/semantic/resolver/expr.rs#L60, during resolution,

  • it does not happen in --release mode,

  • it does happen on Linux with default settings, with the test case

    expanded to this:
     let long_query = (
       from employees
       filter gross_cost > 0
       group {title} (
           aggregate {
               ct = count this,
           }
       )
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
       sort ct
       filter ct > 200
       take 20
     )
     from long_query
    

@aljazerzen
Copy link
Member

So stack memory usage of our compiler grows linearly with call depth of the PRQL program. Which is not ideal and but would be hard to change.

We can change how fast does it grow with call depth and debugging a little, it looks like we do have a bunch of variables on the stack that could be on the heap. Will optimize a little.

@aljazerzen
Copy link
Member

PS: the stack overflows 658 calls deep (with ulimit -s 8192 and for the long snippet above)

@max-sixty
Copy link
Member

max-sixty commented Jan 18, 2024

  • it happens in prqlc/prql-compiler/src/semantic/resolver/expr.rs#L60, during resolution,

Interesting; this is a bit different from the old location { fn: "<prql_compiler::semantic::resolver::Resolver as prql_compiler::ast::pl::fold::AstFold>::fold_expr", file: "/Users/maximilian/workspace/prql/prql-compiler/src/semantic/resolver.rs", line: 279 }, but possibly because the code has moved around a bit...

Edit: updated in #4104

max-sixty added a commit to max-sixty/prql that referenced this issue Jan 18, 2024
A slicker version of PRQL#2857 (comment) in case that's helpful.

Run with:

```
RUST_BACKTRACE=1 RUST_LOG=trace cargo +nightly test -p prqlc --lib -- long_query_inline --nocapture
```

...may want to redirect to a file since it prints a lot...
@aljazerzen
Copy link
Member

It depends on exactly when the stack is filled, so it will vary with every new variable in a function that requires stack memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Invalid compiler output or panic compiler
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants