I'm wondering if there is any perf benchmark on raw objects vs pointers to objects.
I'm aware that it doesn't make sense to use pointers on reference types (e.g. maps) so please don't mention it.
I'm aware that you "must" use pointers if the data needs to be updated so please don't mention it.
Most of the answers/ docs that I've found basically rephrase the guidelines from the official documentation:
... If the receiver is large, a big struct for instance, it will be much cheaper to use a pointer receiver.
My question is simply what means "large" / "big"? Is a pointer on a string overkill ? what about a struct with two strings, what about a struct 3 string fields??
I think we deal with this use case quite often so it's a fair question to ask. Some advise to don't mind the performance issue but maybe some people want to use the right notation whenever they have to chance even if the performance gain is not signifiant. After all a pointer is not that expensive (i.e. one additional keystroke).
An example where it doesn't make sense to use a pointer is for reference types (slices, maps, and channels)
As mentioned in this thread:
The concept of a reference just means something that serves the purpose of referring you to something. It's not magical.
A pointer is a simple reference that tells you where to look.
A slice tells you where to start looking and how far.
Maps and channels also just tell you where to look, but the data they reference and the operations they support on it are more complex.
The point is that all the actually data is stored indirectly and all you're holding is information on how to access it.
As a result, in many cases you don't need to add another layer of indirection, unless you want a double indirection for some reason.
As twotwotwo details in "Pointers vs. values in parameters and return values", strings, interface values, and function values are also implemented with pointers.
As a consequence, you would rarely need a to use a pointer on those objects.
To quote the official golang documentation
...the consideration of efficiency. If the receiver is large, a big struct for instance, it will be much cheaper to use a pointer receiver.
It's very hard to give you exact conditions since there can be different performance goals. As a rule of thumb, by default, all objects larger than 128 bits should be passed by pointer. Possible exceptions of the rule:
you are writing latency sensitive server, so you want to minimise garbage collection pressure. In order to achieve that your Request struct has byte[8] field instead of pointer to Data struct which holds byte[8]. One allocation instead of two.
algorithm you are writing is more readable when you pass the struct and make a copy
etc.
Related
I get the impression that Rust is intended to be used in highly safe systems. Then I noticed that raw pointers allow arbitrary pointer arithmetic, and they can cause memory safety and security issues.
Basically, a pointer is an object that refers to another object. In most programming languages (I guess) a pointer is actually just a number that refers to a memory address. Rust's raw pointers are really just that - memory addresses. There are other pointer types in Rust (& references, Box, Rc, Arc), for which the compiler can verify that the memory is valid and contains what the program thinks it contains. This is not the case for raw pointers; they can in principle point to any memory location, regardless of the content. Refer to The Book for more details.
Raw pointers can only be dereferenced inside unsafe blocks. These blocks are a way for the programmer to tell the compiler "I know better than you that this is safe and I promise not to do anything stupid".
It is generally best to avoid raw pointers if possible because the compiler cannot reason about their validity, which makes them unsafe in general. Things that make raw pointers unsafe are the potential to...
access a NULL pointer,
access a dangling (freed or invalid) pointer,
free a pointer multiple times,
All these points boil down to dereferencing the pointer. That is, to use the memory pointed to.
However, using raw pointers without dereferencing them is perfectly safe. This has a use case in finding out if two references point to the same object:
fn is_same(a: &i32, b: &i32) -> bool {
a as *const _ == b as *const _
}
Another use case is the foreign function interface (FFI). If you wrap a C function that takes raw pointers as arguments, there is no way around providing them to the function. This is actually unsafe (as is the whole FFI business), because the function is likely to dereference the pointer. This means you are responsible for making sure the pointer is valid, stays valid, and is not freed multiple times.
Finally, raw pointers are used for optimization. For example, the slice iterator uses raw pointers as internal state. This is faster than indices because they avoid range checks during iteration. However, it is also unsafe as far as the compiler is concerned. The library author needs to pay extra attention, so using raw pointers for optimization always comes at the risk of introducing memory bugs that you normally do not have in rust.
In summary, the three main uses of raw pointers are:
"just numbers" - you never access the memory they point to.
FFI - you pass them outside Rust.
memory-mapped I/O - to trigger I/O actions you need to access hardware registers at fixed addresses.
performance - they can be faster than other options, but the compiler won't enforce safety.
As to when raw pointers should be used, the first three points are straight-forward: You will know when they apply because you have to. The last point is more subtle. As with all optimizations, only use them when the benefit outweighs the effort and risk of using them.
A counter example when not to use raw pointers is whenever the other pointer types (& references, Box, Rc, Arc) do the job.
Given the following struct:
type Exp struct {
foo int,
bar *int
}
What is the difference in term of performance when using a pointer or a value in a struct. Is there any overhead or this just two schools of Go programming?
I would use pointers to implement a chained struct but is this the only case we have to use pointers in struct in order to gain performance?
PS: in the above struct we talk about a simple int but it could be any other type (even custom one)
Use the form which is most functionally useful for your program. Basically, this means if it's useful for the value to be nil, then use a pointer.
From a performance perspective, primitive numeric types are always more efficient to copy than to dereference a pointer. Even more complex data structures are still usually faster to copy if they are smaller than a cache line or two (under 128 bytes is a good rule of thumb for x86 CPUs).
When things get a little larger, you need to benchmark if performance concerns you. CPUs are very efficient at copying data, and there are so many variables involved which will determine the locality and cache friendliness of your data, it really depends on your program's behavior, and the hardware you're using.
This is an excellent series of articles if you want to better understand the how memory and software interact: "What every programmer should know about memory".
In short, I tell people to choose a pointer or not based on the logic of the program, and worry about performance later.
Use a pointer if you need to pass something to be modified.
Use a pointer if you need to determine if something was unset/nil.
Use a pointer if you are using a type that has methods with pointer receivers.
If the size of a pointer is less than the struct member, then using a pointer is more efficient since you don't need to copy the member but just its address. Also, if you want to be able to move or share some part of a structure, it is better to have a pointer so that you can, again, only share the address of the member. See also the golang faqs.
So I'm having a hard time grasping the idea behind pointers and all that memory allocation.
I'm thinking nowadays with computer as powerful as they are right now why do we have to use pointers at all?
Isn't there always a workaround to do things without the help of pointers?
Pointers are an indirection: instead of working with the data itself, you are working with (something) that points to the data. Depending on the semantics of the language, this allows many things: cheaply switch to another instance of data (by setting the pointer to point to another instance), passing pointers allows access to the original data without having to make (a possibly expensive) copy, etc.
Memory allocation is related to pointers, but separate: you can have pointers without allocating memory. The reason you need pointers for memory allocation is that the actual address the allocated block of memory resides is not known at compile time, so you can only access it via a level of indirection (i.e. pointers) -- the compiler statically allocates space for the pointer that will point to the dynamically allocated memory.
Pointers are incredibly powerful. Just because computers have a faster processing time nowdays, doesn't mean that's any reason to abandon something as essential as pointers. Passing around giant chunks of memory on the stack is inefficient at best, catastrophic at worst. With pointers, you only need to maintain a reference to where the data resides, rather than duplicating huge chunks of memory each time you call a function.
Also, if you're copying all the data every time, how do you modify the original data? Aside from returning the copy of the structure in every call that touches it.
I remember reading somewhere that Dijkstra was assessing a student for a programming course; this student was quite intelligent but s/he wasn't able to solve the problem because there was sort of a mental block.
All the code was sort of ok, but what was needed was simply to use the expression
a[a[i+1]] = j;
and even if being so close to the solution still the goal seemed to be miles away.
Languages "without pointers" already exist... e.g. BASIC. Without explicit pointers, that is. But the indirection idea... the idea that you can have data to mean just where to find other data is central to programming.
The very idea of array is about being able to use computed values to find other values.
Trying to hide this idea is an horrible plan. According to Dijkstra anyone that has been exposed to the BASIC language has already received such a mental mutilation that is impossible to recover as a good programmer (and probably the absence of explicit indirection was one of the problems).
I think he was exaggerating.
Just a bit.
There are lots of real-world reasons you'd want to do this. Ours is because we have a list of variable length data structures, and we want to be able to change the size of one of the elements without recopying them all.
Here's a few things I've tried:
Just have a lot of kernel arguments. Sure, sounds hacky, but works for small N. This is actually what we've been doing.
Do 1) with some sort of macro loop which extends the kernel args to the max size (which I think is device dependent). I don't really want to do this... it sounds bad.
Create some sort of list of structs which contain pointers, and fill it before your kernel invocation. I tried this, and I think it violates the spec. According to what I've seen on the nVidia forums, preserving the address of a device pointer beyond one kernel invocation is illegal. If anyone can point to where in the spec it says this, I'd love to know, because I can't find it. However, this definitely breaks on ATI hardware, as it moves the objects around.
Give up, store the variable sized objects in a big array, and write a clever algorithm to use empty space so the whole array must be reflowed less often. This will work, but is an inelegant, complicated design. Also, it requires lots of scary pointer arithmetic...
Does anyone else have other ideas? What about experiences trying to do this; is there a least hacky way? Why?
To 3:
OpenCL 1.1 spec page 193 says "Arguments to kernel functions in a program cannot be declared as a pointer to a pointer(s)."
Struct containing a pointer to pointer (pointer to a buffer object) might not be against strict reading of this sentence but it's within the spirit: No pointers to buffer objects may be passed as arguments from host code to kernel even if they're hidden inside a user defined struct.
I'd opt for option 5: Do not use variable size data structures. If you have any way of making them constant size by all means do it. It will make your life a whole lot easier. To be precise there is no 'variable size structure'. Every struct definition produces constant sized structs, so if the size has changed then the struct itself has changed and therefore requires another mem object. Every pointer passed to kernel function must have a single type.
In addition to sharpnelis answer option 5:
If the objects have similar size you could use unions on the biggest possible object size. But make sure you use explicit alignment. Pass a second buffer identifying the union used in each object in your variable-sized-objects-in-static-size-union buffer.
I reverted to this when using opencl lib code that only allowed one variable array of arbitrary type. I simply used cl_float2 to pass two floats. Since the cl_floatN types are implemented as unions - what works for the build in types will work for you as well.
Do you know if are there pointers in Haskell?
If yes: how do you use them? Are there any problems with them? And why aren't they popular?
If no: is there any reason for it?
Yes there are. Take a look at Foreign.Ptr or Data.IORef
I suspect this wasn't what you are asking for though. As Haskell is for the most part without state, it means pointers don't fit into the language design. Having a pointer to memory outside the function would mean that a function is no longer pure and only allowing pointers to values within the current function is useless.
Haskell does provide pointers, via the foreign function interface extension. Look at, for example, Foreign.Storable.
Pointers are used for interoperating with C code. Not for every day Haskell programming.
If you're looking for references -- pointers to objects you wish to mutate -- there are STRef and IORef, which serve many of the same uses as pointers. However, you should rarely -- if ever -- need Refs.
If you simply wish to avoid copying large values, as sepp2k supposes, then you need do nothing: in most implementation, all non-trivial values are allocated separately on a heap and refer to one another by machine-level addresses (i.e. pointers). But again, you need do nothing about any of this, it is taken care of for you.
To answer your question about how values are passed, they are passed in whatever way the implementation sees fit: since you can't mutate the values anyway, it doesn't impact the meaning of the code (as long as the strictness is respected); usually this works out to by-need unless you're passing in e.g. Int values that the compiler can see have already been evaluated...
Pass-by-need is like pass-by-reference, except that any given reference could refer either to an actual evaluated value (which cannot be changed), or to a "thunk" for a not-yet-evaluated value. Wikipedia has more.