What is the most efficient way to make instance real and joined
Make real and join*

Could make the mesh by making the dupliobject active and running make duplicates real, and then joining them.  Sorry haven't fixed the location properly

import bpy

context = bpy.context
scene = context.scene
vl = context.view_layer

obs = set(scene.objects)
bpy.ops.object.duplicates_make_real()
new_obs = list(set(scene.objects) - obs)
bpy.ops.object.select_all(action='DESELECT')
o = new_obs[0]
vl.objects.active = o
for o in new_obs:
    o.select_set(True)

bpy.ops.object.join()


Using depsgraph in 2.8


Result in edit mode above, default torus duplivert default and scaled down icosphere.  May be cuppa time while it runs

Instances can be obtained from the depsgraph. https://docs.blender.org/api/master/bpy.types.DepsgraphObjectInstance.html#module-bpy.types

There is a section in 

https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/Scene_and_Object_API 

re getting the instances of an object via the python API.

Using the method prescribed for getting instances of a particular object, here is a test script to create a bmesh from all object instances of the context object,  

The bmesh is written to  new single mesh object from the instances.  The mesh equivalent of make real and join.  (Without the original)

I have only tested this on a very simple example, without materials.

import bpy
import bmesh

context = bpy.context
ob = context.object
mwi = ob.matrix_world.inverted()
dg = context.evaluated_depsgraph_get()

bm = bmesh.new()
for ob_inst in dg.object_instances:
    if ob_inst.parent and ob_inst.parent.original == ob:
        me = ob_inst.instance_object.data
        bm.from_mesh(me)
        # transform to match instance
        bmesh.ops.transform(bm,
                matrix=mwi @ ob_inst.matrix_world,
                verts=bm.verts[-len(me.vertices):]
                )

# link an object with the instanced mesh

me = bpy.data.meshes.new(f"{ob.data.name}_InstanceMesh")
bm.to_mesh(me)
ob_ev = bpy.data.objects.new(f"{ob.name}_InstancedObject", me) 
ob_ev.matrix_world = ob.matrix_world

context.collection.objects.link(ob_ev)