Stream: helpdesk (published)

Topic: ✔ Julia spending lots of time in `string_n`


view this post on Zulip Laura Demkowicz-Duffy (Jun 10 2023 at 23:24):

I have some code which tends to hand without exiting or responding a lot of the time it's run (the code path it takes is random), and upon Ctrl-C'ing it or similar, I tend to find the top of the stacktrace looks like this:

image.png

The code in question here is:

"""
    cityindexunchecked(world, id)

Get the index of a [`City`](@ref) into `world.cities` and `world.graph` from it's `id`.

Returns `nothing` if the city isn't found.
"""
function cityindexunchecked(world, id)
    findfirst(c -> c.id == id, world.cities)
end
# Convenience method:"Los Angeles", ["San Francisco", "Chicago", "Mexico City", "Sydney"]),
# integers are not valid ids so we assume c is the index and return it
cityindexunchecked(world, id::Int) = id
cityindexunchecked(world, c::City) = cityindexunchecked(world, c.id)

"""
    cityindex(world, city[, error])

Get the index of a [`City`](@ref) into `world.cities` and `world.graph` from it's `id`.

Throws an error if the city isn't found.
Pass the parameter `error` to override the error text.
`id` may either be a [`City`](@ref) object or just some identifying object.
"""
function cityindex(world, c, e = "City $c not found")
    i = cityindexunchecked(world, c)
    @assert i != nothing e
    return i
end
export cityindex

Can this be the result of the potential string comparison in cityindexunchecked? The type of id is typically a string.

view this post on Zulip mbaz (Jun 11 2023 at 00:37):

My first guess would be that the culprit is the$c in cityindex

view this post on Zulip Sukera (Jun 11 2023 at 06:08):

the stacktrace has cityindex:62, which is likely where your function definition originally is?

view this post on Zulip Sukera (Jun 11 2023 at 06:09):

if so, yes, the interpolation ALWAYS happens, not just when the error is thrown

view this post on Zulip Sukera (Jun 11 2023 at 06:11):

note also the docstring of @assert:

   Warning
  
    An assert might be disabled at various optimization levels. Assert should therefore only be used as a
    debugging tool and not used for authentication verification (e.g., verifying passwords), nor should
    side effects needed for the function to work correctly be used inside of asserts.

So at various optimization levels, the @assert may be removed entirely, leading to a wrong result. I'd suggest the pattern

isnothing(i) || throw(ArgumentError(LazyString("City ", c, " not found"))

which will stay in your code across optimization levels and only interpolate the string when the error is actually thrown.

view this post on Zulip Notification Bot (Jun 11 2023 at 11:31):

Laura Demkowicz-Duffy has marked this topic as resolved.

view this post on Zulip Notification Bot (Jun 11 2023 at 11:31):

Laura Demkowicz-Duffy has marked this topic as resolved.


Last updated: Dec 28 2024 at 04:38 UTC