I stumbled on this behavior when profiling a small finite element code.
julia> N = 10_000;
julia> A = sprand(N, N, 0.01);
julia> @time scale!(A, 2.0);
elapsed time: 7.333984625 seconds (2275708 bytes allocated)
julia> @time scale!(A, 0.5);
elapsed time: 7.258595034 seconds (80 bytes allocated)
julia> @time scale!(A.nzval, 2.0);
elapsed time: 0.022604954 seconds (269764 bytes allocated)
julia> @time scale!(A.nzval, 0.5);
elapsed time: 0.001367558 seconds (80 bytes allocated)
julia> 7.258595034/0.001367558
5307.7054384530675
The problem is that scale! treats A as an AbstractArray.
julia> methods(scale!, (typeof(A),Float64))
1-element Array{Any,1}:
scale!(X::AbstractArray{T,N},s::Number) at linalg/generic.jl:24
If called with A.nzval, however, scale! calls BLAS.scal!