The issue with reading large arrays is that if takes too much time (depends on the node's settings), the call will fail and you won't get any data.
In order to read large arrays, the safest way is to use a pagination pattern.
It's exactly like memory pagination used in every computer, instead of cutting the memory in pages, we cut our array (which is in memory too ;) ).
Here's a very simple example to illustrate how pagination works :
contract Contract {
uint[] public large_array;
function read(uint cursor, uint length) public view returns (uint[] memory) {
uint[] memory array = new uint[](length);
for (uint i = cursor; i < cursor+length; i++) {
array[i] = large_array[i];
}
return array;
}
}
You can read more on the link above, which uses safer methods for reading.
Edit
As Lauri wrote, if your function doesn't modify the state of your contract, you can mark it as view so calling it will be free, with the exception of calling it within a smart contract.
externalwith this question. Let's say a huge array of pixels for the most wasteful way to use an array on EVM: a large picture. The combination of calling, concat, and rendering everything exceeds the avg block time and just isn't fast enough. So I want to pay for a call to return it all at once (I haven't tried this but as far as I know it should work). The question remains should I add external to this function to make it cheaper? – Duncan Brain May 10 '19 at 12:29externalwill only make the call marginally cheaper (I think), since the parameters inreadare just two unsigned integers. – Elisha Drion May 10 '19 at 12:35