<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <generator uri="https://gohugo.io/" version="0.81.0">Hugo</generator><title type="html"><![CDATA[Isaac's blog]]></title>
    
        <subtitle type="html"><![CDATA[Blog about my favorite topics]]></subtitle>
    
    
    
            <link href="https://xie.rocks/" rel="alternate" type="text/html" title="HTML" />
            <link href="https://xie.rocks/atom.xml" rel="self" type="application/atom+xml" title="Atom" />
    <updated>2022-01-17T02:31:29+00:00</updated>
    
    <id>https://xie.rocks/</id>
        
        <entry>
            <title type="html"><![CDATA[C#内存相关类型理解]]></title>
            <link href="https://xie.rocks/posts/system-memory/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://xie.rocks/posts/system-memory/</id>
            
            <published>2021-07-30T10:05:46+08:00</published>
            <updated>2022-01-17T10:30:16+08:00</updated>
            
            
            <content type="html"><![CDATA[<h2 id="memory-access-pattern">memory access pattern</h2>
<p>In .NET world, there are three types of memory you may be interested:</p>
<ol>
<li>Managed heap memory, such as an array;</li>
<li>Stack memory, such as objects created by stackalloc;</li>
<li>Native memory, such as a native pointer reference.</li>
</ol>
<p>Each type of memory access may need to use language features that are designed for it:</p>
<p>To access heap memory, use the fixed (pinned) pointer on supported types (like string), or use other appropriate .NET types that have access to it, such as an array or a buffer;
To access stack memory, use pointers with stackalloc;
To access unmanaged system memory, use pointers with Marshal APIs.
You see, different access pattern needs different code, no single built-in type for all contiguous memory access.</p>
<h2 id="systemmemoryt">System.Memory<code>&lt;T&gt;</code></h2>
<div class="highlight"><pre class="chroma"><code class="language-C#" data-lang="C#"><span class="k">readonly</span> <span class="k">struct</span> <span class="nc">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">IEquatable</span><span class="p">&lt;</span><span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;&gt;</span>
<span class="p">{</span>
    <span class="c1">// The highest order bit of _index is used to discern whether _object is a pre-pinned array.
</span><span class="c1"></span>    <span class="c1">// (_index &lt; 0) =&gt; _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
</span><span class="c1"></span>    <span class="c1">//       (else) =&gt; Pin() needs to allocate a new GCHandle to pin the object.
</span><span class="c1"></span>    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">object?</span> <span class="n">_object</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span> <span class="n">_index</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span> <span class="n">_length</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><h3 id="注解">注解</h3>
<p>与 Span<T> 类似， Memory<T> 表示一段连续的内存。 不同点在于 Memory<T> 不是 ref struct。 这意味着， Memory<T> 可以放置在托管堆上，而 Span<T> 不能。 因此，Memory<T> 没有 Span<T> 的那些限制。 具体而言：</p>
<ul>
<li>它可用作类中的字段。</li>
<li>它可以跨 await 和 yield 边界使用  。
除了Memory<T>之外 ，还可以使用 System.ReadOnlyMemory<T> 来表示不可变或只读内存。</li>
</ul>
<h3 id="object可以是">object可以是：</h3>
<ol>
<li>T[]</li>
<li>MemoryManager<code>&lt;T&gt;</code></li>
<li>T=char &amp;&amp; object=string</li>
<li>T=byte/Char8 &amp;&amp; object=Utf8String</li>
</ol>
<h3 id="隐式转换">隐式转换：</h3>
<ol>
<li>ArraySegment<code>&lt;T&gt;</code> to Memory<code>&lt;T&gt;</code></li>
<li>Memory<code>&lt;T&gt;</code> to ReadOnlyMemory<code>&lt;T&gt;</code></li>
<li>T[] to Memory<code>&lt;T&gt;</code></li>
</ol>
<h2 id="arraysegmentt">ArraySegment<code>&lt;T&gt;</code></h2>
<p>表示一维数组中的一段区域</p>
<div class="highlight"><pre class="chroma"><code class="language-C#" data-lang="C#"><span class="k">readonly</span> <span class="k">struct</span> <span class="nc">ArraySegment</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">IList</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;,</span> <span class="n">IReadOnlyList</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="n">T</span><span class="p">[]?</span> <span class="n">_array</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span> <span class="n">_offset</span><span class="p">;</span> 
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span> <span class="n">_count</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><h2 id="memorymanagert">MemoryManager<code>&lt;T&gt;</code></h2>
<p>MemoryManager<T> 是一个抽象基类，实现 MemoryManager<T> 的类型可以达到替换 Memory<T> 作用。</p>
<div class="highlight"><pre class="chroma"><code class="language-C#" data-lang="C#"><span class="k">abstract</span> <span class="k">class</span> <span class="nc">MemoryManager</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">IMemoryOwner</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;,</span> <span class="n">IPinnable</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">virtual</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">Memory</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">,</span> <span class="n">GetSpan</span><span class="p">().</span><span class="n">Length</span><span class="p">);</span>
    <span class="k">public</span> <span class="k">abstract</span> <span class="n">Span</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">GetSpan</span><span class="p">();</span>
    <span class="k">public</span> <span class="k">abstract</span> <span class="n">MemoryHandle</span> <span class="n">Pin</span><span class="p">(</span><span class="kt">int</span> <span class="n">elementIndex</span> <span class="p">=</span> <span class="m">0</span><span class="p">);</span>
    <span class="k">public</span> <span class="k">abstract</span> <span class="k">void</span> <span class="n">Unpin</span><span class="p">();</span>

    <span class="k">protected</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">CreateMemory</span><span class="p">(</span><span class="kt">int</span> <span class="n">length</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">,</span> <span class="n">length</span><span class="p">);</span>
    <span class="k">protected</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">CreateMemory</span><span class="p">(</span><span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">length</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="n">Memory</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">length</span><span class="p">);</span>
    <span class="k">protected</span> <span class="k">internal</span> <span class="k">virtual</span> <span class="kt">bool</span> <span class="n">TryGetArray</span><span class="p">(</span><span class="k">out</span> <span class="n">ArraySegment</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">segment</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div><h2 id="ref-struct">ref struct</h2>
<p>ref struct是仅在堆栈上的值类型(也被称为嵌入式引用)：</p>
<ol>
<li>表现一个顺序结构的布局；（译注：可以理解为连续内存）</li>
<li>只能在堆栈上使用 <strong>(stack only)</strong> 。即用作方法参数和局部变量；</li>
<li>不能是类或正常结构的静态或实例成员；</li>
<li>不能是异步方法或lambda表达式的方法参数；</li>
<li>不能动态绑定、装箱、拆箱、包装或转换。</li>
</ol>
<h2 id="spant">Span<code>&lt;T&gt;</code></h2>
<p>类型安全和内存安全地表示一段连续内存，它是一个ref struct， <strong>只能在stack上分配内存, 而不能在heap上分配内存</strong>, 但是它的实例可以指向托管内存、原生内存或者栈上内存</p>
<div class="highlight"><pre class="chroma"><code class="language-C#" data-lang="C#"><span class="k">readonly</span> <span class="k">ref</span> <span class="k">struct</span> <span class="nc">Span</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">internal</span> <span class="k">readonly</span> <span class="n">ByReference</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">_pointer</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="kt">int</span> <span class="n">_length</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>]]></content>
            
                 
                    
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[手机连接windows共享文件夹]]></title>
            <link href="https://xie.rocks/posts/windows-share/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://xie.rocks/posts/windows-share/</id>
            
            <published>2021-01-24T17:49:00+08:00</published>
            <updated>2022-01-17T10:30:16+08:00</updated>
            
            
            <content type="html"><![CDATA[<p>长期以来，手机和PC的文件互传能力总是不太令人满意，虽然国产手机厂商在这方面做一了一些努力，但是个人感觉还是不尽如意，并且不够通用。
其实有一个通用的方案，就是SMB协议，ios和android可以通过smb协议连接windows的共享文件夹。iOS13已经原生支持了SMB协议，Android也只需要下载一个SMB客户端就行。</p>
<h2 id="设置windows共享文件夹">设置windows共享文件夹</h2>
<h3 id="新建windows本地账户">新建windows本地账户</h3>
<p>本人经过多次尝试，发现使用微软在线账号来连接widnows共享文件夹总会失败，原因未知。使用本地账户一次就连上了。</p>
<p>在开始菜单搜索“计算机管理”，并打开计算机管理，切到本地用户和组，进入用户选项卡，然后右键菜单选中新建用户。</p>
<p><img src="new_user.png" alt="这是图片" title="新建本地账户"></p>
<h3 id="设置windows共享文件夹-1">设置windows共享文件夹</h3>
<p><img src="share_directory1.png" alt="这是图片" title="设置共享文件夹">
<img src="share_directory2.png" alt="这是图片" title="设置共享文件夹">
<img src="share_directory3.png" alt="这是图片" title="设置共享文件夹"></p>
<h3 id="设置共享文件夹权限">设置共享文件夹权限</h3>
<p><img src="share_directory4.png" alt="这是图片" title="设置共享权限">
<img src="share_directory5.png" alt="这是图片" title="设置共享权限">
<img src="share_directory6.png" alt="这是图片" title="设置共享权限"></p>
<h2 id="设置iphone连接">设置iPhone连接</h2>
<p><img src="IMG_1.PNG" alt="这是图片" title="IOS设置">
<img src="IMG_2.PNG" alt="这是图片" title="IOS设置">
<img src="IMG_3.PNG" alt="这是图片" title="IOS设置">
<img src="IMG_4.PNG" alt="这是图片" title="IOS设置"></p>
<h2 id="设置android-andsmb客户端连接">设置Android AndSMB客户端连接</h2>
<p><img src="android1.jpg" alt="这是图片" title="IOS设置">
<img src="android2.jpg" alt="这是图片" title="IOS设置"></p>]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://xie.rocks/tags/iphone" term="iphone" label="iphone" />
                             
                                <category scheme="https://xie.rocks/tags/android" term="android" label="android" />
                             
                                <category scheme="https://xie.rocks/tags/windows" term="windows" label="windows" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[面试题汇总]]></title>
            <link href="https://xie.rocks/posts/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/?utm_source=atom_feed" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://xie.rocks/posts/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/</id>
            
            <published>2021-01-21T23:14:12+08:00</published>
            <updated>2021-01-21T23:14:12+08:00</updated>
            
            
            <content type="html"><![CDATA[<p>最近参加了数十个公司的后台开发岗位面试，有些面试官问到了一些有意思的题目，个人觉得有必要记录下来，方便以后面试复习。</p>
<h2 id="题目列表">题目列表</h2>
<ol>
<li>
<p>任务系统复杂度体现在哪里？</p>
<ol>
<li>配置规模大，2300 多行，66 列的配置</li>
<li>玩家实际接取的任务数量多，超过 500 多个任务。</li>
<li>代码量多，15000 行左右的代码，</li>
<li>支持任务目标多，超过 100 多种不同的任务目标</li>
<li>大量被其他系统所引用，超过 90 个代码文件里面引用了任务系统</li>
</ol>
</li>
<li>
<p>lua metatable 的用处</p>
</li>
<li>
<p>C++ 多态 虚函数机制介绍</p>
</li>
<li>
<p>二叉树遍历</p>
<ul>
<li>按遍历顺序分为：前序，中序，后序</li>
<li>按实现方式：递归，循环+栈数据结构，Morris Traversal</li>
</ul>
</li>
<li>
<p>stl shuffle的实现</p>
</li>
</ol>
<div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++">    <span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">RandomIt</span> <span class="o">&gt;</span>
    <span class="kt">void</span> <span class="n">random_shuffle</span><span class="p">(</span> <span class="n">RandomIt</span> <span class="n">first</span><span class="p">,</span> <span class="n">RandomIt</span> <span class="n">last</span> <span class="p">)</span>
    <span class="p">{</span>
        <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">RandomIt</span><span class="o">&gt;::</span><span class="n">difference_type</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">last</span> <span class="o">-</span> <span class="n">first</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="o">--</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">first</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">first</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">rand</span><span class="p">()</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)]);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="c1">//来自 &lt;https://en.cppreference.com/w/cpp/algorithm/random_shuffle&gt; 
</span></code></pre></div><ol start="6">
<li>
<p>多线程开发需要注意的点？</p>
<ul>
<li>能不用就不用。单线程程序易写易调易维护。如果决定采用多线程，想清楚收益，最好能预估</li>
<li>尽量不共享数据</li>
<li>如果要共享数据，Go 不要以共享内存的方式来通信，相反，要通过通信来共享内存</li>
<li>如果要共享数据
<ul>
<li>如果只是一些简单数据共享，还可以使用原子类型。（如计算变量之类的）</li>
<li>如果一定需要自定义临界区，尽量使用互斥锁 mutex, 多读少写的情况下使用读写锁，理顺锁的顺序避免死锁发生</li>
</ul>
</li>
</ul>
</li>
<li>
<p>如何避免死锁？</p>
<ul>
<li>线程之间交错执行
<ul>
<li>解决：以固定的顺序加锁</li>
</ul>
</li>
<li>执行某方法时就需要持有锁，且不释放
<ul>
<li>解决：缩减同步代码块范围，最好仅操作共享变量时才加锁</li>
</ul>
</li>
<li>永久等待
<ul>
<li>解决：使用 tryLock()定时锁，超过时限则返回错误信息</li>
</ul>
</li>
</ul>
</li>
<li>
<p>出现死锁怎么检测？</p>
<ul>
<li>检测有向图是否存在环，从一个节点出发深度优化搜索，对访问过的节点进行标记，如果访问了已标记的节点，就表示有向图存在环。</li>
</ul>
</li>
<li>
<p>条件变量用来干什么的</p>
<ul>
<li>条件变量是线程可用的一种同步机制，条件变量给多个线程提供一个回合的场所。条件变量与互斥量一次使用，允许线程以无竞争的方式等待一个特定的条件发生。</li>
</ul>
</li>
<li>
<p>redis 基础数据结构介绍？</p>
</li>
<li>
<p>红黑树和跳跃表比较</p>
<ol>
<li>时间复杂度差不多，跳跃表实现简单，方便调试和 review</li>
<li>跳跃表范围查找更方便（因为有 next 指针）</li>
<li>跳跃表并发支持更好，红黑树插入删除有 rebalance 的过程，会涉及到比较多的节点，而跳跃表因为是链表结构，并发加锁的粒度就会小一些，并发支持就更友好一些。</li>
</ol>
</li>
<li>
<p>自己的优势？</p>
<ul>
<li>肯专研，喜欢去看源码</li>
<li>喜欢去接触新的技术，或者是提高工作效率的东西</li>
</ul>
</li>
<li>
<p>自己的劣势？
*比较好说话了，不够强势。</p>
</li>
<li>
<p>挑战最大的事情？怎么解决的？</p>
</li>
<li>
<p>缓存一致性</p>
</li>
<li>
<p>扩容</p>
</li>
<li>
<p>缩容</p>
</li>
<li>
<p>单点</p>
</li>
<li>
<p>故障自愈</p>
</li>
<li>
<p>并发量大处理不过来怎么办？</p>
</li>
<li>
<p>epoll 与 select 区别</p>
</li>
<li>
<p>进程与线程调度区别？</p>
</li>
<li>
<p>大数相乘的实现</p>
</li>
<li>
<p>格子最短路径数统计</p>
</li>
<li>
<p>背包问题</p>
</li>
<li>
<p>排行榜服务器实现 （上榜、下榜逻辑）</p>
</li>
<li>
<p>好友服务器实现 （添加好友、删除好友逻辑）</p>
</li>
<li>
<p>匹配服务器实现，以及如何选战斗服务器（ds)</p>
</li>
<li>
<p>有序数组去除重复元素</p>
</li>
<li>
<p>链表，将倒数 K 个节点，移到链表前面</p>
</li>
</ol>]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="https://xie.rocks/tags/%E9%9D%A2%E8%AF%95" term="%E9%9D%A2%E8%AF%95" label="面试" />
                             
                                <category scheme="https://xie.rocks/tags/C&#43;&#43;" term="C&#43;&#43;" label="C&#43;&#43;" />
                            
                        
                    
                
            
        </entry>
    
</feed>
