当前位置: 首页 > news >正文

米拓建站模板旅游景区网站建设规划方案

米拓建站模板,旅游景区网站建设规划方案,可以做招商的网站,高密建网站Java技术体系方向-JVM虚拟机参数调优原理 内容简介栈上分配与逃逸分析逃逸分析(Escape Analysis)栈上分配基本思想使用场景线程私有对象 虚拟机内存逻辑图JVM内存分配源码#xff1a;代码总体逻辑 在某些场景使用栈上分配设置JVM运行参数#xff1a;开启逃逸模式#xff0c;… Java技术体系方向-JVM虚拟机参数调优原理 内容简介栈上分配与逃逸分析逃逸分析(Escape Analysis)栈上分配基本思想使用场景线程私有对象 虚拟机内存逻辑图JVM内存分配源码代码总体逻辑 在某些场景使用栈上分配设置JVM运行参数开启逃逸模式关闭TLAB运行结果查看内存使用情况 结论调整JVM运行参数关闭逃逸模式开启TLAB查看内存使用情况运行结果 结论 调整JVM运行参数关闭逃逸关闭TLAB运行结果查看内存使用情况 运行结果对比调整分配空间大小运行结果经过对比得出结论 TLAB的基本介绍TLABThread Local Allocation Buffer特点开启TLAB的参数TLAB的源码TLAB的数据结构 分配规则指针碰撞Eden区分配运行结果 G1垃圾回收过程触发混合回收条件混合回收范围混合回收过程初始标记并发标记最终标记 混合回收混合回收失败时 内容简介 本文主要针对于综合层面上进行分析JVM优化方案总结和列举调优参数计划。主要包含 调优之逃逸分析栈上分配调优之线程局部缓存TLAB调优之G1回收器 栈上分配与逃逸分析 -XX:DoEscapeAnalysis 逃逸分析(Escape Analysis) 逃逸分析的基本行为就是分析对象动态作用域当一个对象在方法中被定义后它可能被外部方法所引用称为方法逃逸。 方法逃逸的几种方式如下 public class EscapeTest {public static Object obj;// 给全局变量赋值发生逃逸public void globalVariableEscape() {obj new Object();}// 方法返回值发生逃逸public Object methodEscape() {return new Object();}// 实例引用发生逃逸public void instanceEscape() {test(this);} }栈上分配 栈上分配是Java虚拟机提供的一种优化技术 基本思想 “对于那些线程私有的对象指的是不可能被其他线程访问的对象可以将它们直接分配在栈上而不是分配在堆上”。 分配在栈上的好处可以在函数调用结束后自行销毁而不需要垃圾回收器的介入减轻GC压力从而提升系统的性能。 使用场景 线程私有对象 受虚拟机栈空间的约束适用小对象大对象无法触发虚拟机栈上分配。 线程私有变量大对象虚拟机会分配到TLAB中TLABThread Local Allocation Buffer 在栈上分配该对象的内存,当栈帧从Java虚拟机栈中弹出就自动销毁这个对象。减小垃圾回收器压力。 虚拟机内存逻辑图 JVM内存分配源码 new关键字直接进行分配内存机制源码如下 CASE(_new): {u2 index Bytes::get_Java_u2(pc1);ConstantPool* constants istate-method()-constants();// 如果目标Java类已经解析if (!constants-tag_at(index).is_unresolved_klass()) {// Make sure klass is initialized and doesnt have a finalizerKlass* entry constants-slot_at(index).get_klass();assert(entry-is_klass(), Should be resolved klass);Klass* k_entry (Klass*) entry;assert(k_entry-oop_is_instance(), Should be InstanceKlass);InstanceKlass* ik (InstanceKlass*) k_entry;// 如果符合快速分配场景if ( ik-is_initialized() ik-can_be_fastpath_allocated() ) {size_t obj_size ik-size_helper();oop result NULL;// If the TLAB isnt pre-zeroed then well have to do itbool need_zero !ZeroTLAB;if (UseTLAB) {result (oop) THREAD-tlab().allocate(obj_size);}// 如果TLAB分配失败就在Eden区分配if (result NULL) {need_zero true;// Try allocate in shared edenretry:// 指针碰撞分配HeapWord* compare_to *Universe::heap()-top_addr();HeapWord* new_top compare_to obj_size;if (new_top *Universe::heap()-end_addr()) {if (Atomic::cmpxchg_ptr(new_top, Universe::heap()-top_addr(), compare_to) ! compare_to) {goto retry;}result (oop) compare_to;}}if (result ! NULL) {// Initialize object (if nonzero size and need) and then the header// TLAB区清零if (need_zero ) {HeapWord* to_zero (HeapWord*) result sizeof(oopDesc) / oopSize;obj_size - sizeof(oopDesc) / oopSize;if (obj_size 0 ) {memset(to_zero, 0, obj_size * HeapWordSize);}}if (UseBiasedLocking) {result-set_mark(ik-prototype_header());} else {result-set_mark(markOopDesc::prototype());}result-set_klass_gap(0);result-set_klass(k_entry);// 将对象地址压入操作数栈栈顶SET_STACK_OBJECT(result, 0);// 更新程序计数器PC取下一条字节码指令继续处理UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);}}}// Slow case allocation// 慢分配CALL_VM(InterpreterRuntime::_new(THREAD, METHOD-constants(), index),handle_exception);SET_STACK_OBJECT(THREAD-vm_result(), 0);THREAD-set_vm_result(NULL);UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);}代码总体逻辑 JVM再分配内存时总是优先使用快分配策略当快分配失败时才会启用慢分配策略。 如果Java类没有被解析过直接进入慢分配逻辑。快速分配策略如果没有开启栈上分配或者不符合条件则会进行TLAB分配。快速分配策略如果TLAB分配失败则尝试Eden区分配。如果Eden区分配失败则进入慢分配策略。如果对象满足直接进入老年代的条件那就直接进入老年代分配。快速分配对于热点代码如果开启逃逸分析JVM自会执行栈上分配或者标量替换等优化方案。 在某些场景使用栈上分配 设置JVM运行参数 -Xmx10m -Xms10m -XX:DoEscapeAnalysis -XX:-UseTLAB -XX:PrintGC 开启逃逸模式关闭TLAB /*** description 开启逃逸模式关闭线程本地缓存模式TLABjdk1.8默认开启* -Xmx10m -Xms10m -XX:DoEscapeAnalysis -XX:-UseTLAB -XX:PrintGC */ public class AllocationOnStack {public static void main(String[] args) throws InterruptedException {long start System.currentTimeMillis();for (int index 0; index 100000000; index) {allocate();}long end System.currentTimeMillis();System.out.println((end - start) ms);Thread.sleep(1000*1000);// 看后台堆情况来佐证关闭逃逸优化后是走的堆分配。}public static void allocate() {byte[] bytes new byte[2];bytes[0] 1;bytes[1] 1;} }运行结果 [GC (Allocation Failure) 2048K-520K(9728K), 0.0008938 secs] [GC (Allocation Failure) 2568K-520K(9728K), 0.0006386 secs] 6 msjstat -gc pid 查看内存使用情况 结论 看出栈上分配机制的速度非常快只需要6ms就完成了实现GC 调整JVM运行参数 关闭逃逸模式开启TLAB -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:UseTLAB -XX:PrintGC 查看内存使用情况 运行结果 [GC (Allocation Failure) 2048K-504K(9728K), 0.0013831 secs] [GC (Allocation Failure) 2552K-512K(9728K), 0.0010576 secs] [GC (Allocation Failure) 2560K-400K(9728K), 0.0022408 secs] [GC (Allocation Failure) 2448K-448K(9728K), 0.0006095 secs] [GC (Allocation Failure) 2496K-416K(9728K), 0.0010540 secs] [GC (Allocation Failure) 2464K-464K(8704K), 0.0007620 secs] [GC (Allocation Failure) 1488K-381K(9216K), 0.0007714 secs] [GC (Allocation Failure) 1405K-381K(9216K), 0.0004409 secs] [GC (Allocation Failure) 1405K-381K(9216K), 0.0004725 secs] ....... [GC (Allocation Failure) 2429K-381K(9728K), 0.0008293 secs] [GC (Allocation Failure) 2429K-381K(9728K), 0.0009006 secs] [GC (Allocation Failure) 2429K-381K(9728K), 0.0005553 secs] [GC (Allocation Failure) 2429K-381K(9728K), 0.0005077 secs] 894 ms结论 可以看出来关闭了栈上分配后不但YGC次数增加了并且总体事件也变长了总体事件894ms 调整JVM运行参数 -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:-UseTLAB -XX:PrintGC 关闭逃逸关闭TLAB 运行结果 [GC (Allocation Failure) 2048K-472K(9728K), 0.0007073 secs] [GC (Allocation Failure) 2520K-528K(9728K), 0.0009216 secs] [GC (Allocation Failure) 2576K-504K(9728K), 0.0005897 secs] [GC (Allocation Failure) 2551K-424K(9728K), 0.0005780 secs] [GC (Allocation Failure) 2472K-440K(9728K), 0.0006923 secs] [GC (Allocation Failure) 2488K-456K(8704K), 0.0006277 secs] [GC (Allocation Failure) 1480K-389K(9216K), 0.0005560 secs] ....... [GC (Allocation Failure) 2437K-389K(9728K), 0.0003227 secs] [GC (Allocation Failure) 2437K-389K(9728K), 0.0004264 secs] [GC (Allocation Failure) 2437K-389K(9728K), 0.0004396 secs] [GC (Allocation Failure) 2437K-389K(9728K), 0.0002773 secs] [GC (Allocation Failure) 2437K-389K(9728K), 0.0002766 secs] 1718 ms查看内存使用情况 运行结果对比 运行耗时开启逃逸 VS关闭逃逸(开启TLAB)VS关闭逃逸(关闭TLAB)) 6ms VS 894ms VS 1718ms虚拟机内存回收开启逃逸VS关闭逃逸 调整分配空间大小 /*** since 2019/8/13 上午6:55* -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:UseTLAB -XX:PrintCommandLineFlags -XX:PrintGC*/ public class AllocationOnStack {private static final int _1B 65;public static void main(String[] args) throws InterruptedException {long start System.currentTimeMillis();for (int index 0; index 100000000; index) {allocateBigSpace();}long end System.currentTimeMillis();System.out.println(end - start);Thread.sleep(1000*1000);// 看后台堆情况来佐证关闭逃逸优化后是走的堆分配。}public static void allocate() {byte[] bytes new byte[2];bytes[0] 1;bytes[1] 1;}public static void allocateBigSpace() {byte[] allocation1;allocation1 new byte[1 * _1B];} }运行结果 -XX:DoEscapeAnalysis -XX:InitialHeapSize5242880 -XX:MaxHeapSize5242880 -XX:PrintCommandLineFlags -XX:PrintGC -XX:UseCompressedClassPointers -XX:UseCompressedOops -XX:UseParallelGC -XX:-UseTLAB[GC (Allocation Failure) 1023K-516K(5632K), 0.0028410 secs] [GC (Allocation Failure) 1540K-578K(5632K), 0.0023265 secs] ........ [GC (Allocation Failure) 2466K-1442K(5632K), 0.0013395 secs] [GC (Allocation Failure) 2466K-1442K(5632K), 0.0004367 secs] 8925调整启动参数 -XX:DoEscapeAnalysis -XX:-UseTLAB 运行结果: -XX:DoEscapeAnalysis -XX:InitialHeapSize5242880 -XX:MaxHeapSize5242880 -XX:PrintCommandLineFlags -XX:PrintGC -XX:UseCompressedClassPointers -XX:UseCompressedOops -XX:UseParallelGC -XX:-UseTLAB[GC (Allocation Failure) 1023K-516K(5632K), 0.0028410 secs] [GC (Allocation Failure) 1540K-578K(5632K), 0.0023265 secs] ........ [GC (Allocation Failure) 2466K-1442K(5632K), 0.0013395 secs] [GC (Allocation Failure) 2466K-1442K(5632K), 0.0004367 secs] 8925经过对比得出结论 分配内存为64byte -XX:-UseTLAB 经过多次测试发现当_1B64b时效率还是非常高一旦大于64b就会急剧下降。所以推断出64byte是JVM选择是TLAB分配 OR Eden区分配的临界值。 TLAB的基本介绍 TLABThread Local Allocation Buffer 线程本地分配缓存这是一个线程独享的内存分配区域。 特点 TLAB解决了直接在线程共享堆上安全分配带来的线程同步性能消耗问题解决了指针碰撞。 TLAB内存空间位于Eden区。 默认TLAB大小为占用Eden Space的1%。 开启TLAB的参数 -XX:UseTLAB-XX:TLABSize-XX:TLABRefillWasteFraction-XX:TLABWasteTargetPercent-XX:PrintTLAB TLAB的源码 TLAB的数据结构 class ThreadLocalAllocBuffer: public CHeapObjmtThread {HeapWord* _start; // address of TLABHeapWord* _top; // address after last allocationHeapWord* _pf_top; // allocation prefetch watermarkHeapWord* _end; // allocation end (excluding alignment_reserve)size_t _desired_size; // desired size (including alignment_reserve)size_t _refill_waste_limit; // hold onto tlab if free() is larger than this }_start 指TLAB连续内存起始地址。_top 指TLAB当前分配到的地址。_end 指TLAB连续内存截止地址。_desired_size 是指TLAB的内存大小。_refill_waste_limit 是指最大的浪费空间。默认值为64b eg假设为_refill_waste_limit5KB 假如当前TLAB已经分配96KB还剩下4KB可分配但是现在new了一个对象需要6KB的空间显然TLAB的内存不够了4kb5kb这时只浪费4KB的空间在_refill_waste_limit之内这时可以申请一个新的TLAB空间原先的TLAB交给Eden管理。 假如当前TLAB已经分配90KB还剩下10KB现在new了一个对象需要11KB显然TLAB的内存不够了这时就不能简单的抛弃当前TLAB这11KB会被安排到Eden区进行申请。 分配规则 obj_size tlab_top tlab_end直接在TLAB空间分配对象。 obj_size tlab_top tlab_end tlab_free tlab_refill_waste_limit 对象不在TLAB分配在Eden区分配。tlab_free剩余的内存空间tlab_refill_waste_limit允许浪费的内存空间 tlab剩余可用空间tlab可浪费空间当前线程不能丢弃当前TLAB本次申请交由Eden区分配空间。 obj_size tlab_top tlab_end tlab_free _refill_waste_limit重新分配一块TLAB空间在新的TLAB中分配对象。 tlab剩余可用空间tlab可浪费空间在当前允许可浪费空间内重新申请一个新TLAB空间原TLAB交给Eden。 清单/src/share/vm/memory/ThreadLocalAllocationBuffer.inline.hpp功能TLAB内存分配 inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) {invariants();// 获取当前topHeapWord* obj top();if (pointer_delta(end(), obj) size) {// successful thread-local allocation #ifdef ASSERT// Skip mangling the space corresponding to the object header to// ensure that the returned space is not considered parsable by// any concurrent GC thread.size_t hdr_size oopDesc::header_size();Copy::fill_to_words(obj hdr_size, size - hdr_size, badHeapWordVal); #endif // ASSERT// This addition is safe because we know that top is// at least size below end, so the add cant wrap.// 重置topset_top(obj size);invariants();return obj;}return NULL; }实际上虚拟机内部会维护一个叫作refill_waste的值当剩余对象空间大于refill_waste时会选择在堆中分配若小于该值则会废弃当前TLAB新建TLAB来分配对象。 这个阈值可以使用TLABRefillWasteFraction来调整它表示TLAB中允许产生这种浪费的比例。 默认值为64即表示使用约为1/64的TLAB空间作为refill_waste。 TLAB和refill_waste都会在运行时不断调整的使系统的运行状态达到最优。 如果想要禁用自动调整TLAB的大小可以使用-XX:-ResizeTLAB禁用ResizeTLAB 使用-XX:TLABSize手工指定一个TLAB的大小。 指针碰撞Eden区分配 // 指针碰撞分配 HeapWord* compare_to *Universe::heap()-top_addr(); HeapWord* new_top compare_to obj_size; if (new_top *Universe::heap()-end_addr()) {if (Atomic::cmpxchg_ptr(new_top, Universe::heap()-top_addr(), compare_to) ! compare_to) {goto retry;}result (oop) compare_to;} }Eden区指针碰撞需要模拟多线程并发申请内存空间。 /*** since 2019/8/19 下午11:25 -Xmx100m -Xms100m -XX:-DoEscapeAnalysis -XX:UseTLAB -XX:TLABWasteTargetPercent1 -XX:PrintCommandLineFlags -XX:PrintGCDetails*/ public class AllocationTLABSomeThread {private static final int threadNum 100;private static CountDownLatch latch new CountDownLatch(threadNum);private static final int n 50000000 / threadNum;private static void alloc() {byte[] b new byte[100];}public static void main(String[] args) {long start System.currentTimeMillis();for (int i 0; i threadNum; i) {new Thread(() - {for (int j 0; j n; j) {alloc();}latch.countDown();}).start();}try {latch.await();} catch (InterruptedException e) {System.out.println(hello world);}long end System.currentTimeMillis();System.out.println(end - start);}}且需要关闭逃逸分析 -XX:-DoEscapeAnalysis -XX:UseTLAB 运行结果 -XX:-DoEscapeAnalysis -XX:InitialHeapSize104857600 -XX:MaxHeapSize104857600 -XX:PrintCommandLineFlags -XX:PrintGCDetails -XX:TLABWasteTargetPercent1 -XX:UseCompressedClassPointers -XX:UseCompressedOops -XX:UseParallelGC -XX:UseTLAB [GC (Allocation Failure) [PSYoungGen: 25600K-960K(29696K)] 25600K-968K(98304K), 0.0019559 secs] [Times: user0.01 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 26560K-960K(29696K)] 26568K-968K(98304K), 0.0022243 secs] [Times: user0.01 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 26560K-768K(29696K)] 26568K-776K(98304K), 0.0022446 secs] [Times: user0.00 sys0.00, real0.00 secs] ........ [GC (Allocation Failure) [PSYoungGen: 32768K-0K(33280K)] 34193K-1425K(101888K), 0.0014598 secs] [Times: user0.01 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 32768K-0K(33280K)] 34193K-1425K(101888K), 0.0015168 secs] [Times: user0.00 sys0.01, real0.00 secs] 823 HeapPSYoungGen total 33280K, used 3655K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)eden space 32768K, 11% used [0x00000007bdf00000,0x00000007be291c48,0x00000007bff00000)from space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)to space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)ParOldGen total 68608K, used 1425K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)object space 68608K, 2% used [0x00000007b9c00000,0x00000007b9d64798,0x00000007bdf00000)Metaspace used 4255K, capacity 4718K, committed 4992K, reserved 1056768Kclass space used 477K, capacity 533K, committed 640K, reserved 1048576K关闭逃逸和TLAB分配 -XX:-DoEscapeAnalysis -XX:-UseTLAB 运行结果 -XX:-DoEscapeAnalysis -XX:InitialHeapSize104857600 -XX:MaxHeapSize104857600 -XX:PrintCommandLineFlags -XX:PrintGCDetails -XX:TLABWasteTargetPercent1 -XX:UseCompressedClassPointers -XX:UseCompressedOops -XX:UseParallelGC -XX:-UseTLAB [GC (Allocation Failure) [PSYoungGen: 25599K-976K(29696K)] 25599K-984K(98304K), 0.0023516 secs] [Times: user0.01 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 26575K-880K(29696K)] 26583K-888K(98304K), 0.0015459 secs] [Times: user0.01 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 26480K-832K(29696K)] 26488K-840K(98304K), 0.0006776 secs] [Times: user0.00 sys0.00, real0.00 secs] ....... [GC (Allocation Failure) [PSYoungGen: 32767K-0K(33280K)] 34053K-1285K(101888K), 0.0004838 secs] [Times: user0.00 sys0.00, real0.00 secs] [GC (Allocation Failure) [PSYoungGen: 32767K-0K(33280K)] 34053K-1285K(101888K), 0.0005389 secs] [Times: user0.00 sys0.00, real0.01 secs] 5388 HeapPSYoungGen total 33280K, used 21392K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)eden space 32768K, 65% used [0x00000007bdf00000,0x00000007bf3e4230,0x00000007bff00000)from space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)to space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)ParOldGen total 68608K, used 1285K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)object space 68608K, 1% used [0x00000007b9c00000,0x00000007b9d41788,0x00000007bdf00000)Metaspace used 4248K, capacity 4718K, committed 4992K, reserved 1056768Kclass space used 478K, capacity 533K, committed 640K, reserved 1048576K经过对比相差7倍左右。二者内存回收♻️从YoungGC次数和耗时上没有太大变化应为都是Eden区分配。 G1垃圾回收过程 触发混合回收条件 -XX:InitiatingHeapOccupancyPercent45 当老年代空间使用占整个堆空间45%时。 混合回收范围 新生代、老年代、大对象。 混合回收过程 初始标记 这个过程会STW停止系统线程。 标记GC-Roots的直接引用对象。 线程栈中局部变量表 。方法区中的静态变量/常量等。本地方法栈。 特点速度极快。 并发标记 这个过程不会STW系统线程正常运行。从第一阶段标记的GC-Roots开始追踪所有存活对象。 特点慢很耗时。优化JVM会对“并发标记”阶段新产生的对象及对象修改做记录RememberSet 最终标记 这个过程会STW系统线程停止运行。会根据“并发标记”阶段记录的RememberSet进行对象标记。 特点很快。RememberSet相当于是拿空间换时间。 混合回收 这个过程会STW系统线程停止运行。会计算老年代中每个Region中存活对象数量存活对象占比执行垃圾回收预期耗时和效率。 耗时会根据启动参数中-XX:MaxGCPauseMillis200和历史回收耗时来计算本次要回收多少老年代Region才能耗时200ms。 特点回收了一部分远远没有达到回收的效果G1还有一个特殊处理方法STW后进行回收然后恢复系统线程然后再次STW执行混合回收掉一部分Region‐XX:G1MixedGCCountTarget8 (默认是8次)反复执行上述过程8次。 注意假设要回收400个Region如果受限200ms每次只能回收50个Region反复8次刚好全部回收完毕。这么做的好处是避免单次停顿回收STW时间太长。 **还有一个参数要提一下‐XX:G1HeapWastePercent5 (默认是5%)。 混合回收是采用复制算法把要回收的Region中存活的对象放入其他Region中。然后这个Region中的垃圾全部清理掉这样就会不断有Region释放出来当释放出的Region占整个堆空间5%时停止混合回收。 还有一个参数‐XX:G1MixedGCLiveThresholdPercent85 (默认值85%) 。回收Region的时候必须是存活对象低于85%。 混合回收失败时 在Mixed回收的时候无论是年轻代还是老年代都是基于复制算法进行回收都要把各个Region的存活对象拷贝到另外其他的Region里去万一拷贝是发生空间不足就会触发一次失败。 一旦回收失败立马就会切换采用Serial 单线程进行标记清理整理整个过程是非常慢的灾难。
http://www.zqtcl.cn/news/333153/

相关文章:

  • 网站建设的开发方式知乎科技部网站建设合同范本
  • 兰州市建设厅官方网站做酒店的网站
  • 宠物店网站开发文档撰写洛阳市河阳建设工程有限公司网站
  • 毕业设计做网站应该学什么wordpress调用子分类
  • 怎么建网站做淘宝客用国外网站 图片做自媒体
  • 汕头建站模板搭建怎么制作有效网站
  • 学生个人网站作品怎么wordpress用的什么主题
  • 设计logo网站侵权吗知乎一键做单页网站
  • 网站服务器有什么用做视频网站视频存放问题
  • 影评网站建设可以免费发布招聘网站
  • 富阳做兼职的网站正邦设计上海分公司
  • 网站漏洞解决办法投资
  • wordpress网站如何网页设计实训总结3000字大学篇
  • 用ps怎么做网站导航条wordpress 开启缩略图
  • 网上销售型的企业网站为什么要域名备案
  • 唐山网站建设方案优化国内酷炫网站
  • 国外网站备案吗网站做一样没有侵权吧
  • 谷歌怎么建网站ps中怎样做网站轮播图片
  • 汕头有没有做网站廊坊宣传片制作公司
  • 百度快速收录网站有些人做网站不用钱的 对吗
  • 如何规划一个网站网站建设预付费入什么科目
  • 北京做网站的好公司有哪些网站建设杭州缘择低价
  • 建设网站团队张掖响应式建站平台
  • 中国建设之乡是哪里网站优化连云港哪家强?
  • 网站建设报价是多少30号长沙封城最新消息
  • 常州专业网站建设费用电商推广技巧
  • 辽源市网站建设南通营销网站开发
  • 新站优化案例去韩国用什么地图导航
  • 宁波网站制作与推广WordPress怎么文章分类
  • mvc 做网站国内的搜索引擎有哪些